u-boot.lists.denx.de archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] introduce Arm FF-A support
@ 2022-03-29 15:16 abdellatif.elkhlifi
  2022-03-29 15:16 ` [PATCH 1/6] arm_ffa: introduce Arm FF-A low-level driver abdellatif.elkhlifi
                   ` (7 more replies)
  0 siblings, 8 replies; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-03-29 15:16 UTC (permalink / raw)
  To: u-boot; +Cc: nd, trini, Abdellatif El Khlifi

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

This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).

FF-A support is generic by design and can be used by any Arm platform.

The features added are as follows:
    
1/ FF-A device driver
2/ armffa command
3/ FF-A Sandbox driver
4/ FF-A Sandbox test cases
5/ FF-A MM communication


The suggested design sees FF-A as a data bus allowing data exchange with the firmware
running under TrustZone HW (such as Optee). The same approach was followed in the
FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))

u-boot boards using FF-A can provide a device tree node in a <board>-u-boot.dtsi file.
Since the node can not be hosted in Linux device tree, we suggest using u-boot device tree.

As a use case, we will send  a commit enabling FF-A for the Corstone-1000 platform and providing
the FF-A node in u-boot.dtsi files.

Corstone-1000: https://lore.kernel.org/u-boot/20220322104118.573537-1-rui.silva@linaro.org/

Cc: Tom Rini <trini@konsulko.com>

Abdellatif El Khlifi (6):
  arm_ffa: introduce Arm FF-A low-level driver
  arm_ffa: introduce armffa command
  arm_ffa: introduce the FF-A Sandbox driver
  arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: introduce FF-A MM communication

 MAINTAINERS                           |   15 +
 arch/arm/cpu/armv8/cache.S            |   16 +
 arch/arm/cpu/armv8/cache_v8.c         |    3 +-
 arch/arm/cpu/armv8/smccc-call.S       |   27 +
 arch/arm/lib/asm-offsets.c            |    6 +
 arch/sandbox/dts/sandbox.dtsi         |   10 +
 arch/sandbox/dts/test.dts             |   10 +
 cmd/Kconfig                           |   10 +
 cmd/Makefile                          |    2 +
 cmd/armffa.c                          |  266 +++++
 common/board_r.c                      |    7 +
 configs/sandbox64_defconfig           |    2 +
 configs/sandbox_defconfig             |    2 +
 doc/arch/sandbox.rst                  |    1 +
 drivers/Kconfig                       |    2 +
 drivers/Makefile                      |    1 +
 drivers/arm-ffa/Kconfig               |   32 +
 drivers/arm-ffa/Makefile              |    7 +
 drivers/arm-ffa/arm-ffa-uclass.c      |  102 ++
 drivers/arm-ffa/arm_ffa_prv.h         |  200 ++++
 drivers/arm-ffa/core.c                | 1463 +++++++++++++++++++++++++
 drivers/arm-ffa/sandbox.c             |  735 +++++++++++++
 drivers/arm-ffa/sandbox_arm_ffa_prv.h |  128 +++
 include/arm_ffa.h                     |  197 ++++
 include/arm_ffa_helper.h              |   45 +
 include/dm/uclass-id.h                |    1 +
 include/linux/arm-smccc.h             |   28 +-
 include/mm_communication.h            |    4 +-
 include/sandbox_arm_ffa.h             |   31 +
 include/sandbox_arm_ffa_helper.h      |   26 +
 lib/Kconfig                           |    1 +
 lib/Makefile                          |    1 +
 lib/arm-ffa/Kconfig                   |    6 +
 lib/arm-ffa/Makefile                  |    9 +
 lib/arm-ffa/arm_ffa_helper.c          |  188 ++++
 lib/arm-ffa/sandbox_arm_ffa_helper.c  |   23 +
 lib/efi_loader/Kconfig                |   14 +-
 lib/efi_loader/efi_boottime.c         |   17 +
 lib/efi_loader/efi_variable_tee.c     |  294 ++++-
 test/cmd/Makefile                     |    1 +
 test/cmd/armffa.c                     |   33 +
 test/cmd/armffa.h                     |   13 +
 test/dm/Makefile                      |    1 +
 test/dm/ffa.c                         |  424 +++++++
 test/dm/ffa.h                         |   22 +
 45 files changed, 4415 insertions(+), 11 deletions(-)
 create mode 100644 cmd/armffa.c
 create mode 100644 drivers/arm-ffa/Kconfig
 create mode 100644 drivers/arm-ffa/Makefile
 create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/arm-ffa/core.c
 create mode 100644 drivers/arm-ffa/sandbox.c
 create mode 100644 drivers/arm-ffa/sandbox_arm_ffa_prv.h
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_helper.h
 create mode 100644 include/sandbox_arm_ffa.h
 create mode 100644 include/sandbox_arm_ffa_helper.h
 create mode 100644 lib/arm-ffa/Kconfig
 create mode 100644 lib/arm-ffa/Makefile
 create mode 100644 lib/arm-ffa/arm_ffa_helper.c
 create mode 100644 lib/arm-ffa/sandbox_arm_ffa_helper.c
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/cmd/armffa.h
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/dm/ffa.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH 1/6] arm_ffa: introduce Arm FF-A low-level driver
  2022-03-29 15:16 [PATCH 0/6] introduce Arm FF-A support abdellatif.elkhlifi
@ 2022-03-29 15:16 ` abdellatif.elkhlifi
  2022-03-29 15:16 ` [PATCH 2/6] arm_ffa: introduce armffa command abdellatif.elkhlifi
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-03-29 15:16 UTC (permalink / raw)
  To: u-boot; +Cc: nd, trini, Abdellatif El Khlifi

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

Add the driver implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A)
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology. This driver uses SMC32 calling convention.

The driver provides helper FF-A interfaces for user layers.
These helper functions allow clients to pass data and select the
FF-A function to use for the communication with secure world.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
---
 MAINTAINERS                      |    8 +
 arch/arm/cpu/armv8/smccc-call.S  |   27 +
 arch/arm/lib/asm-offsets.c       |    6 +
 common/board_r.c                 |    7 +
 drivers/Kconfig                  |    2 +
 drivers/Makefile                 |    1 +
 drivers/arm-ffa/Kconfig          |   25 +
 drivers/arm-ffa/Makefile         |    6 +
 drivers/arm-ffa/arm-ffa-uclass.c |   65 ++
 drivers/arm-ffa/arm_ffa_prv.h    |  200 +++++
 drivers/arm-ffa/core.c           | 1427 ++++++++++++++++++++++++++++++
 include/arm_ffa.h                |  190 ++++
 include/arm_ffa_helper.h         |   45 +
 include/dm/uclass-id.h           |    1 +
 include/linux/arm-smccc.h        |   28 +-
 lib/Kconfig                      |    1 +
 lib/Makefile                     |    1 +
 lib/arm-ffa/Kconfig              |    6 +
 lib/arm-ffa/Makefile             |    8 +
 lib/arm-ffa/arm_ffa_helper.c     |  188 ++++
 lib/efi_loader/efi_boottime.c    |   17 +
 21 files changed, 2258 insertions(+), 1 deletion(-)
 create mode 100644 drivers/arm-ffa/Kconfig
 create mode 100644 drivers/arm-ffa/Makefile
 create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/arm-ffa/core.c
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_helper.h
 create mode 100644 lib/arm-ffa/Kconfig
 create mode 100644 lib/arm-ffa/Makefile
 create mode 100644 lib/arm-ffa/arm_ffa_helper.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 74d5263fb1..c5b608eb60 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -232,6 +232,14 @@ F:	board/CZ.NIC/
 F:	configs/turris_*_defconfig
 F:	include/configs/turris_*.h
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	drivers/arm-ffa/
+F:	include/arm_ffa.h
+F:	include/arm_ffa_helper.h
+F:	lib/arm-ffa/
+
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..9a6aebf194 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
@@ -45,3 +47,28 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+	.macro FFASMCCC instr
+	.cfi_startproc
+	\instr	#0
+	ldr	x9, [sp]
+	stp	x0, x1, [x9, #ARM_SMCCC_RES_X0_OFFS]
+	stp	x2, x3, [x9, #ARM_SMCCC_RES_X2_OFFS]
+	stp	x4, x5, [x9, #ARM_SMCCC_RES_X4_OFFS]
+	stp	x6, x7, [x9, #ARM_SMCCC_RES_X6_OFFS]
+	ret
+	.cfi_endproc
+	.endm
+
+/*
+ * void arm_ffa_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
+ *		  unsigned long a3, unsigned long a4, unsigned long a5,
+ *		  unsigned long a6, unsigned long a7, struct arm_smccc_res *res)
+ */
+ENTRY(__arm_ffa_smccc_smc)
+	FFASMCCC	smc
+ENDPROC(__arm_ffa_smccc_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 22fd541f9a..02a4a42fe6 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,8 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * (C) Copyright 2022 ARM Limited
  */
 
 #include <common.h>
@@ -115,6 +117,10 @@ int main(void)
 #ifdef CONFIG_ARM_SMCCC
 	DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+	DEFINE(ARM_SMCCC_RES_X4_OFFS, offsetof(struct arm_smccc_res, a4));
+	DEFINE(ARM_SMCCC_RES_X6_OFFS, offsetof(struct arm_smccc_res, a6));
+#endif
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
 #endif
diff --git a/common/board_r.c b/common/board_r.c
index b92c1bb0be..7866ec3ad5 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -62,6 +62,10 @@
 #include <asm-generic/gpio.h>
 #include <efi_loader.h>
 
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+#include <arm_ffa_helper.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -771,6 +775,9 @@ static init_fnc_t init_sequence_r[] = {
 	INIT_FUNC_WATCHDOG_RESET
 	initr_net,
 #endif
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+	ffa_helper_init_device,
+#endif
 #ifdef CONFIG_POST
 	initr_post,
 #endif
diff --git a/drivers/Kconfig b/drivers/Kconfig
index b26ca8cf70..e83c23789d 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
 
 source "drivers/adc/Kconfig"
 
+source "drivers/arm-ffa/Kconfig"
+
 source "drivers/ata/Kconfig"
 
 source "drivers/axi/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 4e7cf28440..6671d2a604 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -107,6 +107,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
new file mode 100644
index 0000000000..e503dfaebf
--- /dev/null
+++ b/drivers/arm-ffa/Kconfig
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC if ARM64
+	select LIB_UUID
+	select ARM_FFA_TRANSPORT_HELPERS
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  This driver is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In u-boot FF-A design, the Secure World is considered as one
+	  entity to communicate with. FF-A communication is handled by
+	  one device and one instance. This device takes care of
+	  all the interactions between Normal world and Secure World.
diff --git a/drivers/arm-ffa/Makefile b/drivers/arm-ffa/Makefile
new file mode 100644
index 0000000000..7bc9a336a9
--- /dev/null
+++ b/drivers/arm-ffa/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+#
+
+obj-y += arm-ffa-uclass.o core.o
diff --git a/drivers/arm-ffa/arm-ffa-uclass.c b/drivers/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..0bf661d397
--- /dev/null
+++ b/drivers/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <arm_ffa.h>
+#include <errno.h>
+#include <log.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+UCLASS_DRIVER(ffa) = {
+	.name		= "ffa",
+	.id		= UCLASS_FFA,
+};
+
+/**
+ * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher
+ * @func_id:	The FF-A function to be used
+ * @func_data:  Pointer to the FF-A function arguments
+ *				container structure. This also includes
+ *				pointers to the returned data needed by
+ *				clients.
+ *
+ * This runtime function passes the FF-A function ID and its arguments to
+ * the FF-A driver dispatcher.
+ * This function is called by the FF-A helper functions.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int __ffa_runtime ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *func_data)
+{
+	if (!ffa_device_get_ops()->invoke_func)
+		return -EINVAL;
+
+	return ffa_device_get_ops()->invoke_func(func_id, func_data);
+}
+
+/**
+ * ffa_init_device - probes the arm_ffa device
+ *
+ * This boot time function makes sure the arm_ffa device is probed
+ * and ready for use.
+ * This function is called automatically at initcalls
+ * level (after u-boot relocation).
+ *
+ * Arm FF-A transport is implemented through a single u-boot
+ * device (arm_ffa). So, there is only one device belonging to UCLASS_FFA.
+ * All FF-A clients should use the arm_ffa device to use the FF-A
+ * transport.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int ffa_init_device(void)
+{
+	return ffa_get_device();
+}
diff --git a/drivers/arm-ffa/arm_ffa_prv.h b/drivers/arm-ffa/arm_ffa_prv.h
new file mode 100644
index 0000000000..c788d0bd53
--- /dev/null
+++ b/drivers/arm-ffa/arm_ffa_prv.h
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <arm_ffa.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <dm/read.h>
+
+/*
+ * This header is private. It is exclusively used by the FF-A driver
+ */
+
+/* FF-A driver version definitions */
+
+#define MAJOR_VERSION_MASK		GENMASK(30, 16)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/* The FF-A SMC function prototype definition */
+
+typedef void (*invoke_ffa_fn_t)(unsigned long a0, unsigned long a1,
+			unsigned long a2, unsigned long a3, unsigned long a4,
+			unsigned long a5, unsigned long a6, unsigned long a7,
+			struct arm_smccc_res *res);
+
+/**
+ * enum ffa_conduit - Arm FF-A conduits supported by the Arm FF-A driver
+ * Currently only SMC32 is supported.
+ */
+enum ffa_conduit {
+	FFA_CONDUIT_SMC = 0,
+};
+
+/**
+ * FFA_DECLARE_ARGS - FF-A functions local variables
+ * @a0-a7:	local variables used to set registers x0-x7
+ * @res:	the structure hosting the FF-A function return data
+ *
+ * A helper macro for declaring local variables for the FF-A functions  arguments.
+ * The x0-x7 registers are used to exchange data with the secure world.
+ * But, only the bottom 32-bit of thes registers contains the data.
+ */
+#define FFA_DECLARE_ARGS \
+	unsigned long a0 = 0; \
+	unsigned long a1 = 0; \
+	unsigned long a2 = 0; \
+	unsigned long a3 = 0; \
+	unsigned long a4 = 0; \
+	unsigned long a5 = 0; \
+	unsigned long a6 = 0; \
+	unsigned long a7 = 0; \
+	struct arm_smccc_res res = {0}
+
+/* FF-A error codes */
+#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_INTERRUPTED				(-5)
+#define FFA_ERR_STAT_DENIED				(-6)
+#define FFA_ERR_STAT_RETRY				(-7)
+#define FFA_ERR_STAT_ABORTED				(-8)
+
+/**
+ * struct ffa_features_desc - FF-A functions features
+ * @func_id:	FF-A function
+ * @field1:	features read from register w2
+ * @field2:	features read from register w3
+ *
+ * Data structure describing the features of the  FF-A functions queried by
+ * FFA_FEATURES
+ */
+struct ffa_features_desc {
+	u32 func_id;
+	u32 field1;
+	u32 field2;
+};
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/*
+ * Number of the FF-A interfaces features descriptors
+ * currently only FFA_RXTX_MAP descriptor is supported
+ */
+#define FFA_FEATURE_DESC_CNT (1)
+
+/**
+ * struct ffa_pdata - platform data for the arm_ffa device
+ * @conduit: The FF-A conduit used
+ *
+ * Platform data structure read from the device tree
+ */
+struct ffa_pdata {
+	enum ffa_conduit conduit;
+};
+
+/**
+ * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ *
+ * Data structure hosting the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	u64 rxbuf; /* virtual address */
+	u64 txbuf; /* virtual address */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @UUID:	UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	union ffa_partition_uuid UUID;
+};
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * This data structure contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* virtual address */
+};
+
+/**
+ * struct 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
+ * @conduit:	The selected conduit
+ * @invoke_ffa_fn:	The function executing the FF-A function
+ * @features:	Table of the FF-A functions having features
+ *
+ * The driver data structure hosting all resident data.
+ */
+struct ffa_prvdata {
+	struct udevice *dev;
+	u32 fwk_version;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+	enum ffa_conduit conduit;
+	invoke_ffa_fn_t invoke_ffa_fn;
+	struct ffa_features_desc features[FFA_FEATURE_DESC_CNT];
+};
+
+#endif
diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c
new file mode 100644
index 0000000000..9d0dab1d36
--- /dev/null
+++ b/drivers/arm-ffa/core.c
@@ -0,0 +1,1427 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include "arm_ffa_prv.h"
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <common.h>
+#include <dm.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+#include <log.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <string.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * The device private data structure containing all the resident
+ * data read from secure world
+ */
+struct ffa_prvdata __ffa_runtime_data ffa_priv_data = {0};
+
+/*
+ * Driver functions
+ */
+
+/**
+ * ffa_get_device - probes the arm_ffa device
+ *
+ * This boot time function makes sure the arm_ffa device is probed
+ * and ready for use. This is done using uclass_get_device.
+ * The arm_ffa driver belongs to UCLASS_FFA.
+ * This function should be called before using the driver.
+ *
+ * Arm FF-A transport is implemented through a single u-boot
+ * device (arm_ffa). So, there is only one device belonging to UCLASS_FFA.
+ * All FF-A clients should use the arm_ffa device to use the FF-A
+ * transport.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int ffa_get_device(void)
+{
+	int ret;
+	int devnum = 0;
+
+	if (ffa_priv_data.dev)
+		return FFA_ERR_STAT_SUCCESS;
+
+	/*
+	 * searching and probing the device
+	 */
+	ret = uclass_get_device(UCLASS_FFA, devnum, &ffa_priv_data.dev);
+	if (ret) {
+		ffa_err("can not find the device");
+		ffa_priv_data.dev = NULL;
+		return -ENODEV;
+	}
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_get_version - FFA_VERSION handler function
+ *
+ * This is the boot time function that implements FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_get_version(void)
+{
+	u16 major, minor;
+
+	FFA_DECLARE_ARGS;
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	a0 = FFA_VERSION;
+	a1 = FFA_VERSION_1_0;
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
+
+	if (res.a0 == FFA_ERR_STAT_NOT_SUPPORTED) {
+		ffa_err("A Firmware Framework implementation does not exist");
+		return -EOPNOTSUPP;
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
+		ffa_info("Versions are compatible ");
+
+		ffa_priv_data.fwk_version = res.a0;
+
+		return FFA_ERR_STAT_SUCCESS;
+	}
+
+	ffa_info("Versions are incompatible ");
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id - FFA_ID_GET handler function
+ *
+ * This is the boot time function that implements FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(void)
+{
+	FFA_DECLARE_ARGS;
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	a0 = FFA_ID_GET;
+
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
+			ffa_err("This function is not implemented at this FF-A instance");
+			return -EOPNOTSUPP;
+		}
+
+		ffa_err("Undefined error code (%d)", ((int)res.a2));
+		return -EINVAL;
+	}
+	case FFA_SUCCESS:
+	{
+		ffa_priv_data.id = GET_SELF_ENDPOINT_ID(res.a2);
+		ffa_info("endpoint ID is %u", ffa_priv_data.id);
+
+		return FFA_ERR_STAT_SUCCESS;
+	}
+	default:
+	{
+		ffa_err("Undefined response function (0x%lx)", res.a0);
+		return -EINVAL;
+	}
+	}
+}
+
+/**
+ * ffa_get_features_desc - returns the features descriptor of the specified
+ *						FF-A function
+ * @func_id:	the FF-A function which the features are to be retrieved
+ *
+ * This is a boot time function that searches the features descriptor of the
+ * specified FF-A function
+ *
+ * Return:
+ *
+ * When found, the address of the features descriptor is returned. Otherwise, NULL.
+ */
+static struct ffa_features_desc *ffa_get_features_desc(u32 func_id)
+{
+	u32 desc_idx;
+
+	/*
+	 * search for the descriptor of the selected FF-A interface
+	 */
+	for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
+		if (ffa_priv_data.features[desc_idx].func_id == func_id)
+			return &ffa_priv_data.features[desc_idx];
+
+	return NULL;
+}
+
+/**
+ * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP
+ *							argument
+ *
+ * This is the boot time function that implements FFA_FEATURES FF-A function
+ * to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features(void)
+{
+	FFA_DECLARE_ARGS;
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	a0 = FFA_FEATURES;
+	a1 = FFA_RXTX_MAP;
+
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
+			ffa_err("FFA_RXTX_MAP is not implemented at this FF-A instance");
+			return -EOPNOTSUPP;
+		}
+
+		ffa_err("Undefined error code (%d)", ((int)res.a2));
+		return -EINVAL;
+	}
+	case FFA_SUCCESS:
+	{
+		u32 desc_idx;
+
+		/*
+		 * search for an empty descriptor
+		 */
+		for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
+			if (!ffa_priv_data.features[desc_idx].func_id) {
+				/*
+				 * populate the descriptor with
+				 * the interface features data
+				 */
+				ffa_priv_data.features[desc_idx].func_id =
+					FFA_RXTX_MAP;
+				ffa_priv_data.features[desc_idx].field1 =
+					res.a2;
+
+				ffa_info("FFA_RXTX_MAP features data 0x%lx",
+					 res.a2);
+
+				return FFA_ERR_STAT_SUCCESS;
+			}
+
+		ffa_err("Cannot save FFA_RXTX_MAP features data. Descriptors table full");
+		return -ENOBUFS;
+	}
+	default:
+	{
+		ffa_err("Undefined response function (0x%lx)",
+			res.a0);
+		return -EINVAL;
+	}
+	}
+}
+
+/**
+ * ffa_get_rxtx_buffers_pages_cnt - reads from the features data descriptors
+ *						the minimum number of pages in each of the RX/TX
+ *						buffers
+ * @buf_4k_pages: Pointer to the minimum number of pages
+ *
+ * This is the boot time function that  returns the minimum number of pages
+ *  in each of the RX/TX buffers
+ *
+ * Return:
+ *
+ * buf_4k_pages points to the returned number of pages
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_buffers_pages_cnt(size_t *buf_4k_pages)
+{
+	struct ffa_features_desc *desc = NULL;
+
+	if (!buf_4k_pages)
+		return -EINVAL;
+
+	desc = ffa_get_features_desc(FFA_RXTX_MAP);
+	if (!desc)
+		return -EINVAL;
+
+	switch (desc->field1) {
+	case RXTX_4K:
+		*buf_4k_pages = 1;
+		break;
+	case RXTX_16K:
+		*buf_4k_pages = 4;
+		break;
+	case RXTX_64K:
+		*buf_4k_pages = 16;
+		break;
+	default:
+		ffa_err("RX/TX buffer size not supported");
+		return -EINVAL;
+	}
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_free_rxtx_buffers - frees the RX/TX buffers
+ * @buf_4k_pages: the minimum number of pages in each of the RX/TX
+ *			  buffers
+ *
+ * This is the boot time function used to free the RX/TX buffers
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_free_rxtx_buffers(size_t buf_4k_pages)
+{
+	efi_status_t free_rxbuf_ret, free_txbuf_ret;
+
+	ffa_info("Freeing RX/TX buffers");
+
+	free_rxbuf_ret = efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
+	free_txbuf_ret = efi_free_pages(ffa_priv_data.pair.txbuf, buf_4k_pages);
+
+	if (free_rxbuf_ret != EFI_SUCCESS || free_txbuf_ret != EFI_SUCCESS) {
+		ffa_err("Failed to free RX/TX buffers (rx: %lu , tx: %lu)",
+			free_rxbuf_ret,
+			free_txbuf_ret);
+		return -EINVAL;
+	}
+
+	ffa_priv_data.pair.rxbuf = 0;
+	ffa_priv_data.pair.txbuf = 0;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
+ * @buf_4k_pages: the minimum number of pages in each of the RX/TX
+ *			  buffers
+ *
+ * This is the boot time function used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(size_t buf_4k_pages)
+{
+#if CONFIG_IS_ENABLED(EFI_LOADER)
+
+	efi_status_t efi_ret;
+	void *virt_txbuf;
+	void *virt_rxbuf;
+
+	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
+		 buf_4k_pages);
+
+	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				     EFI_BOOT_SERVICES_DATA,
+				     buf_4k_pages,
+				     &ffa_priv_data.pair.rxbuf);
+
+	if (efi_ret != EFI_SUCCESS) {
+		ffa_priv_data.pair.rxbuf = 0;
+		ffa_err("Failure to allocate RX buffer (EFI error: 0x%lx)",
+			efi_ret);
+
+		return -ENOBUFS;
+	}
+
+	ffa_info("RX buffer at virtual address 0x%llx",
+		 ffa_priv_data.pair.rxbuf);
+
+	virt_rxbuf = (void *)ffa_priv_data.pair.rxbuf;
+
+	/*
+	 * make sure the buffer is clean before use
+	 */
+	memset(virt_rxbuf, 0, buf_4k_pages * SZ_4K);
+
+	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				     EFI_RUNTIME_SERVICES_DATA,
+				     buf_4k_pages,
+				     &ffa_priv_data.pair.txbuf);
+
+	if (efi_ret != EFI_SUCCESS) {
+		efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
+		ffa_priv_data.pair.rxbuf = 0;
+		ffa_priv_data.pair.txbuf = 0;
+		ffa_err("Failure to allocate the TX buffer (EFI error: 0x%lx)"
+			, efi_ret);
+
+		return -ENOBUFS;
+	}
+
+	ffa_info("TX buffer at virtual address 0x%llx",
+		 ffa_priv_data.pair.txbuf);
+
+	virt_txbuf = (void *)ffa_priv_data.pair.txbuf;
+
+	/*
+	 * make sure the buffer is clean before use
+	 */
+	memset(virt_txbuf, 0, buf_4k_pages * SZ_4K);
+
+	return FFA_ERR_STAT_SUCCESS;
+
+#else
+	return -ENOBUFS;
+#endif
+}
+
+/**
+ * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
+ * @buf_4k_pages: the minimum number of pages in each of the RX/TX
+ *			  buffers
+ *
+ * This is the boot time function that implements FFA_RXTX_MAP FF-A function
+ * to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers(size_t buf_4k_pages)
+{
+	int ret;
+
+	FFA_DECLARE_ARGS;
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	ret = ffa_alloc_rxtx_buffers(buf_4k_pages);
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	a0 = FFA_RXTX_MAP;
+	a1 = ffa_priv_data.pair.txbuf;
+	a2 = ffa_priv_data.pair.rxbuf;
+	a3 = buf_4k_pages;
+
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		switch (((int)res.a2)) {
+		case FFA_ERR_STAT_INVALID_PARAMETERS:
+			ffa_err("One or more fields in input parameters is incorrectly encoded");
+			ret = -EPERM;
+			break;
+		case FFA_ERR_STAT_NO_MEMORY:
+			ffa_err("Not enough memory");
+			ret = -ENOMEM;
+			break;
+		case FFA_ERR_STAT_DENIED:
+			ffa_err("Buffer pair already registered");
+			ret = -EACCES;
+			break;
+		case FFA_ERR_STAT_NOT_SUPPORTED:
+			ffa_err("This function is not implemented at this FF-A instance");
+			ret = -EOPNOTSUPP;
+			break;
+		default:
+			ffa_err("Undefined error (%d)",
+				((int)res.a2));
+			ret = -EINVAL;
+		}
+		break;
+	}
+	case FFA_SUCCESS:
+		ffa_info("RX/TX buffers mapped");
+		return FFA_ERR_STAT_SUCCESS;
+	default:
+		ffa_err("Undefined response function (0x%lx)",
+			res.a0);
+		ret = -EINVAL;
+	}
+
+	ffa_free_rxtx_buffers(buf_4k_pages);
+
+	return ret;
+}
+
+/**
+ * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
+ *
+ * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_unmap_rxtx_buffers(void)
+{
+	FFA_DECLARE_ARGS;
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	a0 = FFA_RXTX_UNMAP;
+	a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id);
+
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
+			panic("[FFA] FFA_RXTX_UNMAP is not implemented at this FF-A instance\n");
+		else if (((int)res.a2) == FFA_ERR_STAT_INVALID_PARAMETERS)
+			panic("[FFA] There is no buffer pair registered on behalf of the caller\n");
+		else
+			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
+	}
+	case FFA_SUCCESS:
+	{
+		size_t buf_4k_pages = 0;
+		int ret;
+
+		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
+		if (ret != FFA_ERR_STAT_SUCCESS)
+			panic("[FFA] RX/TX buffers unmapped but failure in getting pages count\n");
+
+		ret = ffa_free_rxtx_buffers(buf_4k_pages);
+		if (ret != FFA_ERR_STAT_SUCCESS)
+			panic("[FFA] RX/TX buffers unmapped but failure in freeing the memory\n");
+
+		ffa_info("RX/TX buffers unmapped and memory freed");
+
+		return FFA_ERR_STAT_SUCCESS;
+	}
+	default:
+		panic("[FFA] Undefined response function (0x%lx)", res.a0);
+	}
+}
+
+/**
+ * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
+ *
+ * This is the boot time function that invokes FFA_RX_RELEASE FF-A function
+ * to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer(void)
+{
+	FFA_DECLARE_ARGS;
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	a0 = FFA_RX_RELEASE;
+
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
+			panic("[FFA] FFA_RX_RELEASE is not implemented at this FF-A instance\n");
+		else if (((int)res.a2) == FFA_ERR_STAT_DENIED)
+			panic("[FFA] Caller did not have ownership of the RX buffer\n");
+		else
+			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
+	}
+	case FFA_SUCCESS:
+		return FFA_ERR_STAT_SUCCESS;
+
+	default:
+		panic("[FFA] Undefined response function (0x%lx)\n", res.a0);
+	}
+}
+
+/**
+ * ffa_uuid_are_identical - checks whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * This is a boot time function used by ffa_read_partitions_info to search
+ * for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+int ffa_uuid_are_identical(const union ffa_partition_uuid *uuid1,
+			   const union ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return (!memcmp(uuid1, uuid2, sizeof(union ffa_partition_uuid)));
+}
+
+/**
+ * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
+ *							and saves it in the private structure
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * This is the boot time function that reads the partitions information
+ * returned by the FFA_PARTITION_INFO_GET and saves it in the private
+ * data structure.
+ *
+ * Return:
+ *
+ * The private data structure is updated with the partition(s) information
+ * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(u32 count, union ffa_partition_uuid *part_uuid)
+{
+	if (!count) {
+		ffa_err("No partition detected");
+		return -ENODATA;
+	}
+
+	ffa_info("Reading partitions data from the RX buffer");
+
+#if CONFIG_IS_ENABLED(EFI_LOADER)
+
+	if (!part_uuid) {
+		/*
+		 * querying information of all partitions
+		 */
+		u64 data_pages;
+		u64 data_bytes;
+		efi_status_t efi_ret;
+		size_t buf_4k_pages = 0;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+		int ret;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+		data_pages = efi_size_in_pages(data_bytes);
+
+		/*
+		 * get the RX buffer size in pages
+		 */
+		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
+		if (ret != FFA_ERR_STAT_SUCCESS) {
+			ffa_err("Can not get the RX buffer size (error %d)", ret);
+			return ret;
+		}
+
+		if (data_pages > buf_4k_pages) {
+			ffa_err("Partitions data size exceeds the RX buffer size:");
+			ffa_err("    Sizes in pages: data %llu , RX buffer %lu ",
+				data_pages,
+				buf_4k_pages);
+
+			return -ENOMEM;
+		}
+
+		efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+					     EFI_RUNTIME_SERVICES_DATA,
+					     data_pages,
+					     (u64 *)&ffa_priv_data.partitions.descs);
+
+		if (efi_ret != EFI_SUCCESS) {
+			ffa_priv_data.partitions.descs = NULL;
+
+			ffa_err("Cannot  allocate partitions data buffer (EFI error 0x%lx)",
+				efi_ret);
+
+			return -ENOBUFS;
+		}
+
+		/*
+		 * make sure the buffer is clean before use
+		 */
+		memset(ffa_priv_data.partitions.descs, 0,
+		       data_pages * SZ_4K);
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data.pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			ffa_priv_data.partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			ffa_info("Partition ID %x : info cached",
+				 ffa_priv_data.partitions.descs[desc_idx].info.id);
+		}
+
+		ffa_priv_data.partitions.count = count;
+
+		ffa_info("%d partition(s) found and cached", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data.pair.rxbuf;
+
+		/*
+		 * search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/*
+			 * search the current ID in the cached partitions
+			 */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < ffa_priv_data.partitions.count;
+			     cached_desc_idx++) {
+				/*
+				 * save the UUID
+				 */
+				if (ffa_priv_data.partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					ffa_priv_data.partitions.descs[cached_desc_idx].UUID =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+#else
+#warning "arm_ffa: reading FFA_PARTITION_INFO_GET data not implemented"
+#endif
+
+	return  FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET
+ *							and saves partitions data
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * This is the boot time function that executes the FFA_PARTITION_INFO_GET
+ * to query the partitions data. Then, it calls ffa_read_partitions_info
+ * to save the data in the private data structure.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(union ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	unsigned long a0 = 0;
+	union ffa_partition_uuid query_uuid = {0};
+	unsigned long a5 = 0;
+	unsigned long a6 = 0;
+	unsigned long a7 = 0;
+	struct arm_smccc_res res = {0};
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	a0 = FFA_PARTITION_INFO_GET;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	}
+
+	ffa_priv_data.invoke_ffa_fn(a0, query_uuid.words.a1, query_uuid.words.a2,
+				    query_uuid.words.a3, query_uuid.words.a4,
+				    a5, a6, a7, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		switch (((int)res.a2)) {
+		case FFA_ERR_STAT_INVALID_PARAMETERS:
+			ffa_err("Unrecognized UUID");
+			return -EPERM;
+		case FFA_ERR_STAT_NO_MEMORY:
+			ffa_err("Results cannot fit in RX buffer of the caller");
+			return -ENOMEM;
+		case FFA_ERR_STAT_DENIED:
+			ffa_err("Callee is not in a state to handle this request");
+			return -EACCES;
+		case FFA_ERR_STAT_NOT_SUPPORTED:
+			ffa_err("This function is not implemented at this FF-A instance");
+			return -EOPNOTSUPP;
+		case FFA_ERR_STAT_BUSY:
+			ffa_err("RX buffer of the caller is not free");
+			return -EBUSY;
+		default:
+			ffa_err("Undefined error (%d)", ((int)res.a2));
+			return -EINVAL;
+		}
+	}
+	case FFA_SUCCESS:
+	{
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info(res.a2, part_uuid);
+			if (ret)
+				ffa_err("Failed to read partition(s) data , error (%d)", ret);
+		}
+
+		/*
+		 * return the SP count
+		 */
+		if (part_uuid) {
+			if (!ret)
+				*pcount = res.a2;
+			else
+				*pcount = 0;
+		}
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the secure world
+		 */
+		ret = ffa_release_rx_buffer();
+
+		if (!part_uuid && !res.a2) {
+			ffa_err("[FFA] no partition installed in the system");
+			return -ENODEV;
+		}
+
+		return ret;
+	}
+	default:
+		ffa_err("Undefined response function (0x%lx)", res.a0);
+		return  -EINVAL;
+	}
+}
+
+/**
+ * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
+ * @func_data: Pointer to the FF-A function arguments container structure.
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@data0_size: UUID size
+ *	@data0: pointer to the UUID (little endian)
+ *	@data1_size: size of the number of partitions
+ *				variable
+ *	@data1: pointer to the number of partitions
+ *			 variable. The variable will be set
+ *			 by the driver
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@data0_size: UUID size
+ *	@data0: pointer to the UUID (little endian)
+ *	@data1_size: size of the SPs information buffer
+ *	@data1: pointer to SPs information buffer
+ *		(allocated by the client).
+ *		The buffer will be filled by the driver
+ *
+ * This is the boot time function that queries the secure partition data from
+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * When invoked through a client request, ffa_get_partitions_info should be
+ * called twice. First call is to get from the driver the number of secure
+ * partitions (SPs) associated to a particular UUID.
+ * Then, the caller (client) allocates the buffer to host the SPs data and
+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
+ * buffer.
+ *
+ * To achieve the mechanism described above, ffa_get_partitions_info uses the
+ * following functions:
+ *		ffa_read_partitions_info
+ *		ffa_query_partitions_info
+ *
+ * Return:
+ *
+ * @data1: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer, the buffer will be
+ * filled by the driver.
+ *
+ * On success FFA_ERR_STAT_SUCCESS is returned. Otherwise, failure
+ */
+static int ffa_get_partitions_info(struct ffa_interface_data *func_data)
+{
+	/*
+	 * fill_data:
+	 * 0: return the SP count
+	 * 1: fill SP data and return it to the caller
+	 * -1: undefined mode
+	 */
+	int fill_data = -1;
+	u32 desc_idx, client_desc_idx;
+	union ffa_partition_uuid *part_uuid;
+	u32 client_desc_max_cnt;
+	u32 parts_found = 0;
+
+	if (!func_data) {
+		ffa_err("No function data provided");
+		return -EINVAL;
+	}
+
+	if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs)
+		panic("[FFA] No partition installed\n");
+
+	if (func_data->data0_size == sizeof(union ffa_partition_uuid) &&
+	    func_data->data0 &&
+	    func_data->data1_size == sizeof(u32) &&
+	    func_data->data1) {
+		/*
+		 * data0 (in): pointer to UUID
+		 * data1 (in): pointer to SP count
+		 * Out: SP count returned in the count variable pointed by data1
+		 */
+
+		fill_data = 0;
+
+		ffa_info("Preparing for checking partitions count");
+
+	} else if ((func_data->data0_size == sizeof(union ffa_partition_uuid)) &&
+		   func_data->data0 &&
+		   (func_data->data1_size >= sizeof(struct ffa_partition_info)) &&
+		   !(func_data->data1_size % sizeof(struct ffa_partition_info)) &&
+		   func_data->data1) {
+		/*
+		 * data0 (in): pointer to UUID
+		 * data1 (in): pointer to SPs descriptors buffer
+		 *             (created by the client)
+		 * Out: SPs descriptors returned in the buffer
+		 *      pointed by data1
+		 */
+
+		fill_data = 1;
+
+		client_desc_idx = 0;
+
+		/*
+		 * number of empty descriptors preallocated by the caller
+		 */
+		client_desc_max_cnt =
+			func_data->data1_size / sizeof(struct ffa_partition_info);
+
+		ffa_info("Preparing for filling partitions info");
+
+	} else {
+		ffa_err("Invalid function arguments provided");
+		return -EINVAL;
+	}
+
+	part_uuid = (union ffa_partition_uuid *)func_data->data0;
+
+	ffa_info("Searching partitions using the provided UUID");
+
+	/*
+	 * search in the cached partitions
+	 */
+	for (desc_idx = 0;
+	     desc_idx < ffa_priv_data.partitions.count;
+	     desc_idx++) {
+		if (ffa_uuid_are_identical(&ffa_priv_data.partitions.descs[desc_idx].UUID,
+					   part_uuid)) {
+			ffa_info("Partition ID %x matches the provided UUID",
+				 ffa_priv_data.partitions.descs[desc_idx].info.id);
+
+			parts_found++;
+
+			if (fill_data) {
+				/*
+				 * trying to fill the partition info in data1
+				 */
+
+				if (client_desc_idx < client_desc_max_cnt) {
+					((struct ffa_partition_info *)
+					 func_data->data1)[client_desc_idx++] =
+						ffa_priv_data.partitions.descs[desc_idx].info;
+					continue;
+				}
+
+				ffa_err("Failed to fill the current descriptor client buffer full");
+				return -ENOBUFS;
+			}
+		}
+	}
+
+	if (!parts_found) {
+		int ret;
+
+		ffa_info("No partition found. Querying framework ...");
+
+		ret = ffa_query_partitions_info(part_uuid, &parts_found);
+
+		if (ret == FFA_ERR_STAT_SUCCESS) {
+			if (!fill_data) {
+				*((u32 *)func_data->data1) = parts_found;
+
+				ffa_info("Number of partition(s) found matching the UUID: %d",
+					 parts_found);
+			} else {
+				/*
+				 * we want to read SPs info
+				 */
+
+				/*
+				 * If SPs data filled, retry searching SP info again
+				 */
+				if (parts_found)
+					ret = ffa_get_partitions_info(func_data);
+				else
+					ret = -ENODATA;
+			}
+		}
+
+		return ret;
+	}
+
+	/* partition(s) found */
+	if (!fill_data)
+		*((u32 *)func_data->data1) = parts_found;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_cache_partitions_info - Queries and saves all secure partitions data
+ *
+ * This is a boot time function that invokes FFA_PARTITION_INFO_GET FF-A
+ * function to query from secure world all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in the
+ * resident private data structure and we keep the UUID field empty
+ * (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * This function is called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(void)
+{
+	return ffa_query_partitions_info(NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @func_data: Pointer to the FF-A function arguments container structure.
+ *					The passed arguments:
+ *						@data0_size: partition ID size
+ *						@data0: pointer to the partition ID
+ *						@data1_size: exchanged data size
+ *						@data1: pointer to the data buffer preallocated by
+ *								the client (in/out)
+ *
+ * This is the runtime function that implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 20 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int __ffa_runtime ffa_msg_send_direct_req(struct ffa_interface_data
+						 *func_data)
+{
+	u16 dst_part_id;
+	unsigned long a0 = 0;
+	unsigned long a1 = 0;
+	unsigned long a2 = 0;
+	struct ffa_send_direct_data *msg;
+	struct arm_smccc_res res = {0};
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		return -ENODEV;
+
+	if (!func_data)
+		return -EINVAL;
+
+	/* No partition installed */
+	if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs)
+		return -ENODEV;
+
+	/* Undefined interface parameters */
+	if (func_data->data0_size != sizeof(u16) ||
+	    !func_data->data0 ||
+	    func_data->data1_size != FFA_MSG_SEND_DIRECT_MAX_SIZE ||
+	    !func_data->data1)
+		return -EINVAL;
+
+	dst_part_id = *((u16 *)func_data->data0);
+	msg = func_data->data1;
+
+	a0 = FFA_MSG_SEND_DIRECT_REQ;
+
+	a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id) |
+		PREP_PART_ENDPOINT_ID(dst_part_id);
+
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2,
+				    msg->a3,
+				    msg->a4,
+				    msg->a5,
+				    msg->a6,
+				    msg->a7,
+				    &res);
+
+	while (res.a0 == FFA_INTERRUPT)
+		ffa_priv_data.invoke_ffa_fn(FFA_RUN, res.a1,
+					    0, 0, 0, 0, 0, 0,
+					    &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		switch (((int)res.a2)) {
+		case FFA_ERR_STAT_INVALID_PARAMETERS:
+			/* Invalid endpoint ID or non-zero reserved register */
+			return -EPERM;
+		case FFA_ERR_STAT_ABORTED:
+			/* Message target ran into unexpected error and has aborted */
+			return -ECONNABORTED;
+		case FFA_ERR_STAT_DENIED:
+			/* Callee is not in a state to handle this request */
+			return -EACCES;
+		case FFA_ERR_STAT_NOT_SUPPORTED:
+			/* This function is not implemented at this FF-A instance */
+			return -EOPNOTSUPP;
+		case FFA_ERR_STAT_BUSY:
+			/* Message target is busy */
+			return -EBUSY;
+		default:
+			/* Undefined error */
+			return -ENXIO;
+		}
+	}
+	case FFA_SUCCESS:
+
+		/* Message sent with no response */
+		return FFA_ERR_STAT_SUCCESS;
+
+	case FFA_MSG_SEND_DIRECT_RESP:
+
+		/*
+		 * Message sent with response
+		 * extract the 32-bit wide return data
+		 */
+		msg->a3 = (u32)res.a3;
+		msg->a4 = (u32)res.a4;
+		msg->a5 = (u32)res.a5;
+		msg->a6 = (u32)res.a6;
+		msg->a7 = (u32)res.a7;
+
+		return FFA_ERR_STAT_SUCCESS;
+
+	default:
+		/* Undefined response function */
+		return -ENOENT;
+	}
+}
+
+/**
+ * invoke_ffa_drv_api - The driver dispatcher function
+ * @func_id:	The FF-A function to be used
+ * @func_data:  Pointer to the FF-A function arguments container
+ *					structure. This also includes pointers to the
+ *					returned data needed by clients.
+ * The dispatcher is a runtime function that selects the FF-A function handler
+ * based on the input FF-A function ID.
+ * The input arguments are passed to the handler function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int __ffa_runtime invoke_ffa_drv_api(u32 func_id,
+				     struct ffa_interface_data *func_data)
+{
+	if (!ffa_priv_data.dev)
+		return -ENODEV;
+
+	switch (func_id) {
+	case FFA_PARTITION_INFO_GET:
+		return ffa_get_partitions_info(func_data);
+	case FFA_RXTX_UNMAP:
+		return ffa_unmap_rxtx_buffers();
+	case FFA_MSG_SEND_DIRECT_REQ:
+		return ffa_msg_send_direct_req(func_data);
+	default:
+		/* Undefined FF-A interface */
+		return -EINVAL;
+	}
+}
+
+/**
+ * ffa_init_private_data - Initialization of the private data
+ * @dev:	the arm_ffa device
+ *
+ * This boot time function reads data from the platform data structure
+ * and populates the private data structure
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_init_private_data(struct udevice *dev)
+{
+	struct ffa_pdata *pdata = dev_get_plat(dev);
+
+	ffa_priv_data.conduit = pdata->conduit;
+
+	if (ffa_priv_data.conduit == FFA_CONDUIT_SMC) {
+		ffa_priv_data.invoke_ffa_fn = arm_ffa_smccc_smc;
+	} else {
+		ffa_err("Undefined FF-A conduit (%d)", ffa_priv_data.conduit);
+		return -EINVAL;
+	}
+
+	ffa_info("Conduit is %s",
+		 ((ffa_priv_data.conduit == FFA_CONDUIT_SMC) ?
+		   "SMC" : "NOT SUPPORTED"));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_bind - The driver bind function
+ * @dev:	the arm_ffa device
+ *
+ * Called when the driver is bound with the device based on the DTB node.
+ * The private data structure is cleared before use.
+ * This makes sure that when the device added/removed  multiple times the previous
+ * private structure is cleared.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS
+ */
+static int ffa_bind(struct udevice *dev)
+{
+	memset(&ffa_priv_data, 0, sizeof(ffa_priv_data));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_probe - The driver probe function
+ * @dev:	the arm_ffa device
+ *
+ * Probing is done at boot time and triggered by the uclass device discovery.
+ * At probe level the following actions are done:
+ *	- initialization of the driver private data structure
+ *	- querying from secure world the FF-A framework version
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of the specified FF-A calls
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in the resident private data structure.
+ *
+ * The probe will fail if either FF-A framework is not detected or the
+ * FF-A requests are not behaving correctly. This ensures that the
+ * driver is not installed and its operations are not exported to the clients.
+ * However, once the driver is successfully probed and an FF-A anomaly is
+ * detected when clients invoke the driver operations, the driver cause
+ * u-boot to panic because the client would not know what to do in such conditions.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_probe(struct udevice *dev)
+{
+	int ret;
+	size_t buf_4k_pages = 0;
+
+	ret = ffa_init_private_data(dev);
+
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_get_version();
+
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_get_endpoint_id();
+
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features();
+
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
+
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers(buf_4k_pages);
+
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_cache_partitions_info();
+
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		ffa_free_rxtx_buffers(buf_4k_pages);
+		return ret;
+	}
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_of_to_plat - Reads the device tree node
+ * @dev:	the arm_ffa device
+ *
+ * This boot time function reads data from the device tree node and populates
+ * the platform data structure
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_of_to_plat(struct udevice *dev)
+{
+	struct ffa_pdata *pdata = dev_get_plat(dev);
+	const char *conduit = NULL;
+
+	conduit = dev_read_string(dev, "method");
+
+	if (!conduit) {
+		ffa_err("Failure to read the conduit from device tree");
+		return -EINVAL;
+	}
+
+	if (strcmp("smc", conduit)) {
+		ffa_err("Unsupported conduit");
+		return -EINVAL;
+	}
+
+	pdata->conduit = FFA_CONDUIT_SMC;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_drv_ops - The driver operations runtime structure
+ * @invoke_func:	The driver dispatcher
+ */
+struct ffa_ops __ffa_runtime_data ffa_drv_ops = {
+	.invoke_func = invoke_ffa_drv_api
+};
+
+/**
+ * ffa_device_get_ops - driver operations getter
+ *
+ * Return:
+ * This runtime function returns a pointer to the driver operations structure
+ */
+const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void)
+{
+	return &ffa_drv_ops;
+}
+
+/**
+ * Defining the device tree compatible string
+ */
+
+static const struct udevice_id ffa_match_id[] = {
+	{"arm,ffa", 0},
+	{},
+};
+
+/**
+ * Declaring the arm_ffa driver under UCLASS_FFA
+ */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= "arm_ffa",
+	.of_match	= ffa_match_id,
+	.id		= UCLASS_FFA,
+	.of_to_plat	= ffa_of_to_plat,
+	.probe		= ffa_probe,
+	.bind		= ffa_bind,
+	.plat_auto	= sizeof(struct ffa_pdata),
+};
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..5a2151f8e4
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,190 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/arm-smccc.h>
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * Macros for displaying logs
+ */
+
+#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
+#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
+
+/*
+ * The driver operations success error code
+ */
+#define FFA_ERR_STAT_SUCCESS				(0)
+
+#if CONFIG_IS_ENABLED(EFI_LOADER)
+
+#include <efi_loader.h>
+
+/*
+ * __ffa_runtime_data and __ffa_runtime - controls whether data/code are
+ * available after calling the EFI ExitBootServices service.
+ * Data/code tagged with these keywords are resident (available at boot time and
+ * at runtime)
+ */
+
+#define __ffa_runtime_data __efi_runtime_data
+#define __ffa_runtime __efi_runtime
+
+#else
+
+#define __ffa_runtime_data
+#define __ffa_runtime
+
+#endif
+
+/*
+ * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
+ */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)	FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+
+#define FFA_VERSION				FFA_SMC_32(0x63)
+#define FFA_ID_GET				FFA_SMC_32(0x69)
+#define FFA_FEATURES				FFA_SMC_32(0x64)
+#define FFA_PARTITION_INFO_GET				FFA_SMC_32(0x68)
+#define FFA_RXTX_MAP				FFA_SMC_32(0x66)
+#define FFA_RXTX_UNMAP				FFA_SMC_32(0x67)
+#define FFA_RX_RELEASE				FFA_SMC_32(0x65)
+#define FFA_MSG_SEND_DIRECT_REQ				FFA_SMC_32(0x6F)
+#define FFA_MSG_SEND_DIRECT_RESP				FFA_SMC_32(0x70)
+#define FFA_RUN				FFA_SMC_32(0x6D)
+#define FFA_ERROR				FFA_SMC_32(0x60)
+#define FFA_SUCCESS				FFA_SMC_32(0x61)
+#define FFA_INTERRUPT				FFA_SMC_32(0x62)
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct  __packed ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @a3-a7:	Data read/written from/to w3-w7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+struct __packed ffa_send_direct_data {
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+	u32 a5; /* w5 */
+	u32 a6; /* w6 */
+	u32 a7; /* w7 */
+};
+
+#define FFA_MSG_SEND_DIRECT_MAX_SIZE (sizeof(struct ffa_send_direct_data))
+
+/* UUID data size */
+#define UUID_SIZE (16)
+
+/*
+ * union ffa_partition_uuid - Data union hosting the UUID
+ *							transmitted by FFA_PARTITION_INFO_GET
+ * @words:	data structure giving 32-bit words access to the UUID data
+ * @bytes:	data structure giving byte access to the UUID data
+ *
+ * The structure holds little-endian UUID data.
+ */
+union ffa_partition_uuid {
+	struct __packed words {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+	} words;
+	u8 bytes[UUID_SIZE];
+};
+
+/**
+ * struct ffa_interface_data - generic FF-A interface data structure used to exchange
+ *							data between user layers and the 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 user layers can pass various types of data with different sizes.
+ * The driver internal functions can detect the nature of this data, verfy compliance
+ * then execute the request when appropriate.
+ */
+struct ffa_interface_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 */
+};
+
+/**
+ * struct ffa_ops - The driver operations structure
+ * @invoke_func:	function pointer to the invoke function
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is resident.
+ */
+struct ffa_ops {
+	/* the driver dispatcher */
+	int (*invoke_func)(u32 func_id, struct ffa_interface_data *func_data);
+};
+
+/**
+ * The device driver and the Uclass driver public functions
+ */
+
+/**
+ * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher
+ */
+int __ffa_runtime ffa_get_invoke_func(u32 func_id,
+				      struct ffa_interface_data *func_data);
+
+/**
+ * ffa_device_get_ops - driver operations getter
+ */
+const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void);
+
+/**
+ * ffa_get_device - probes the arm_ffa device
+ */
+int ffa_get_device(void);
+
+/**
+ * ffa_init_device - probes the arm_ffa device
+ */
+int ffa_init_device(void);
+#endif
diff --git a/include/arm_ffa_helper.h b/include/arm_ffa_helper.h
new file mode 100644
index 0000000000..76f7a9fd29
--- /dev/null
+++ b/include/arm_ffa_helper.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_HELPER_H
+#define __ARM_FFA_HELPER_H
+
+#include <arm_ffa.h>
+
+/*
+ * This header is public. Including this header provides all data structures
+ * and definitions needed by clients to use the FF-A transport driver
+ *
+ * It also provides helper functions allowing to pass data and invoke  FF-A functions
+ */
+
+/**
+ * ffa_helper_get_partitions_info - Wrapper function for FFA_PARTITION_INFO_GET
+ */
+int ffa_helper_get_partitions_info(struct ffa_interface_data *func_data);
+
+/**
+ * ffa_helper_unmap_rxtx_buffers - Wrapper function for FFA_RXTX_UNMAP
+ */
+int ffa_helper_unmap_rxtx_buffers(void);
+
+/**
+ * ffa_helper_msg_send_direct_req - Wrapper function for
+ *								FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ */
+int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data
+						 *func_data);
+
+/**
+ * ffa_helper_init_device - Wrapper function for probing the arm_ffa device
+ */
+int ffa_helper_init_device(void);
+
+/**
+ * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
+ */
+int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin);
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 0e26e1d138..a1181b8f48 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -52,6 +52,7 @@ enum uclass_id {
 	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
 	UCLASS_GPIO,		/* Bank of general-purpose I/O pins */
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 7f2be23394..d58c7c104b 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -57,13 +59,17 @@
 #include <linux/types.h>
 /**
  * struct arm_smccc_res - Result from SMC/HVC call
- * @a0-a3 result values from registers 0 to 3
+ * @a0-a7 result values from registers 0 to 7
  */
 struct arm_smccc_res {
 	unsigned long a0;
 	unsigned long a1;
 	unsigned long a2;
 	unsigned long a3;
+	unsigned long a4;
+	unsigned long a5;
+	unsigned long a6;
+	unsigned long a7;
 };
 
 /**
@@ -113,6 +119,26 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
 			unsigned long a5, unsigned long a6, unsigned long a7,
 			struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
 
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+/**
+ * __arm_ffa_smccc_smc() - make SMC calls used for FF-A transport
+ * @a0-a7: arguments passed in 64-bit registers x0 to x7
+ * @res: result values from 64-bit registers x0 to x7
+ *
+ * This function is used to make SMC calls following SMC32 Calling Convention.
+ * The content of the supplied parameters is copied to registers x0 to x7 prior
+ * to the SMC instruction. The SMC call return data is 32-bit data read from
+ * registers x0 tp x7.
+ */
+asmlinkage void __arm_ffa_smccc_smc(unsigned long a0, unsigned long a1,
+				    unsigned long a2, unsigned long a3, unsigned long a4,
+				    unsigned long a5, unsigned long a6, unsigned long a7,
+				    struct arm_smccc_res *res);
+
+#define arm_ffa_smccc_smc __arm_ffa_smccc_smc
+
+#endif
+
 #define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
 
 #define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
diff --git a/lib/Kconfig b/lib/Kconfig
index 3c6fa99b1a..473821b882 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -810,6 +810,7 @@ config SMBIOS_PARSER
 source lib/efi/Kconfig
 source lib/efi_loader/Kconfig
 source lib/optee/Kconfig
+source lib/arm-ffa/Kconfig
 
 config TEST_FDTDEC
 	bool "enable fdtdec test"
diff --git a/lib/Makefile b/lib/Makefile
index 11b03d1cbe..8e6fad6130 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_EFI) += efi/
 obj-$(CONFIG_EFI_LOADER) += efi_driver/
 obj-$(CONFIG_EFI_LOADER) += efi_loader/
 obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/
+obj-$(CONFIG_ARM_FFA_TRANSPORT_HELPERS) += arm-ffa/
 obj-$(CONFIG_LZMA) += lzma/
 obj-$(CONFIG_BZIP2) += bzip2/
 obj-$(CONFIG_TIZEN) += tizen/
diff --git a/lib/arm-ffa/Kconfig b/lib/arm-ffa/Kconfig
new file mode 100644
index 0000000000..79acbc5a8f
--- /dev/null
+++ b/lib/arm-ffa/Kconfig
@@ -0,0 +1,6 @@
+config ARM_FFA_TRANSPORT_HELPERS
+	bool "Enable interface helpers for Arm Firmware Framework for Armv8-A"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  User layers call FF-A interfaces using helper functions which
+	  pass the data and the FF-A function ID to the low level driver
diff --git a/lib/arm-ffa/Makefile b/lib/arm-ffa/Makefile
new file mode 100644
index 0000000000..cba625fde4
--- /dev/null
+++ b/lib/arm-ffa/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+#
+
+# This file only gets included when CONFIG_ARM_FFA_TRANSPORT_HELPERS is set
+
+obj-y += arm_ffa_helper.o
diff --git a/lib/arm-ffa/arm_ffa_helper.c b/lib/arm-ffa/arm_ffa_helper.c
new file mode 100644
index 0000000000..67a3a4e9ab
--- /dev/null
+++ b/lib/arm-ffa/arm_ffa_helper.c
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <arm_ffa_helper.h>
+#include <uuid.h>
+
+/**
+ * ffa_helper_get_partitions_info - Wrapper function for FFA_PARTITION_INFO_GET
+ *
+ * @func_data: Pointer to the FF-A function arguments container
+ *				structure.
+ *				The passed arguments:
+ *					Mode 1: When getting from the driver the number of
+ *						secure partitions:
+ *						@data0_size: UUID size
+ *						@data0: pointer to the UUID (little endian)
+ *						@data1_size: size of the number of partitions
+ *									variable
+ *						@data1: pointer to the number of partitions
+ *								 variable. The variable will be set
+ *								 by the driver
+ *					Mode 2: When requesting the driver to return the
+ *						partitions information:
+ *						@data0_size: UUID size
+ *						@data0: pointer to the UUID (little endian)
+ *						@data1_size: size of the SPs information buffer
+ *						@data1: pointer to SPs information buffer
+ *								(allocated by the client).
+ *							The buffer will be filled by the driver
+ *
+ * This is the boot time function used by clients who wants to get from secure
+ * world the partition(s) information.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The client should use
+ * ffa_helper_get_partitions_info to pass the UUID information to the driver
+ * which uses PARTITION_INFO_GET to obtain the partition(s) information.
+ *
+ * ffa_helper_get_partitions_info should be called twice. First call is to get
+ * from the driver the number of secure partitions (SPs) associated to a
+ * particular UUID. Then, the caller (client) allocates the buffer to host the
+ * SPs data and issues a 2nd call. Then, the driver fills the SPs data in the
+ * pre-allocated buffer.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int ffa_helper_get_partitions_info(struct ffa_interface_data *func_data)
+{
+	return ffa_get_invoke_func(FFA_PARTITION_INFO_GET, func_data);
+}
+
+/**
+ * ffa_helper_unmap_rxtx_buffers - Wrapper function for FFA_RXTX_UNMAP
+ *
+ * This is the boot time function that allows clients to unmap the RX/TX
+ * buffers
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int ffa_helper_unmap_rxtx_buffers(void)
+{
+	return ffa_get_invoke_func(FFA_RXTX_UNMAP, NULL);
+}
+
+/**
+ * ffa_helper_msg_send_direct_req - Wrapper function for
+ *								FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @func_data: Pointer to the FF-A function arguments container structure.
+ * The passed arguments:
+ *	@data0_size: partition ID size
+ *	@data0: pointer to the partition ID
+ *	@data1_size: exchanged data size
+ *	@data1: pointer to the data buffer preallocated by the client (in/out)
+ *
+ * This is the runtime function that allows clients to send data to the secure
+ * world partitions. The arm_ffa driver uses FFA_MSG_SEND_DIRECT_REQ to send the
+ * data to the secure partition. The response from the secure partition is
+ * handled internally by the driver using FFA_MSG_SEND_DIRECT_RESP and returned
+ * to ffa_helper_msg_send_direct_req through @func_data
+ *
+ * The maximum size of the data that can be exchanged is 20 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * The client should pre-allocate a buffer pointed by @data1 which the size
+ * is sizeof(struct ffa_send_direct_data)
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data
+											 *func_data)
+{
+	return ffa_get_invoke_func(FFA_MSG_SEND_DIRECT_REQ, func_data);
+}
+
+/**
+ * ffa_helper_init_device - Wrapper function for probing the arm_ffa device
+ *
+ * This boot time function should be called to probe the arm_ffa device so
+ * it becomes ready for use.
+ * To achieve that, this function is called automatically at initcalls
+ * level (after u-boot relocation).
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int ffa_helper_init_device(void)
+{
+	return ffa_init_device();
+}
+
+/**
+ * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
+ * @uuid_str:	UUID string in big endian format (36 bytes wide + '/0')
+ * @uuid_bin:	preallocated 16 bytes UUID buffer in little endian format
+ *
+ * UUID binary format used by the FF-A framework (16 bytes):
+ *
+ * [LSB] 4B-2B-2B-2B-6B (little endian data fields)
+ *
+ * UUID string is 36 length of characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ * be                be      be       be      be
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a binary UUID, these endianness rules apply:
+ *     be: means the field in the string is considered a big endian hex number
+ *         and should be converted to little endian binary format
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16 = 0;
+	u32 tmp32 = 0;
+	u64 tmp64 = 0;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp32 = simple_strtoul(uuid_str, NULL, 16);
+	memcpy(uuid_bin, &tmp32, 4);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 9, NULL, 16);
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 14, NULL, 16);
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 19, NULL, 16);
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp64 = simple_strtoull(uuid_str + 24, NULL, 16);
+	memcpy(uuid_bin + 10, (char *)&tmp64, 6);
+
+	return 0;
+}
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 5bcb8253ed..cffa2c69d6 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -23,6 +23,10 @@
 #include <asm/setjmp.h>
 #include <linux/libfdt_env.h>
 
+#if defined(CONFIG_ARM_FFA_TRANSPORT)
+#include <arm_ffa_helper.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Task priority level */
@@ -2114,6 +2118,10 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 	struct efi_event *evt, *next_event;
 	efi_status_t ret = EFI_SUCCESS;
 
+#if defined(CONFIG_ARM_FFA_TRANSPORT)
+	int ffa_ret;
+#endif
+
 	EFI_ENTRY("%p, %zx", image_handle, map_key);
 
 	/* Check that the caller has read the current memory map */
@@ -2174,6 +2182,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 		dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
 	}
 
+#if defined(CONFIG_ARM_FFA_TRANSPORT)
+	/* unmap FF-A RX/TX buffers */
+	ffa_ret = ffa_helper_unmap_rxtx_buffers();
+	if (ffa_ret)
+		debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n");
+	else
+		debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
+#endif
+
 	/* Patch out unsupported runtime function */
 	efi_runtime_detach();
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH 2/6] arm_ffa: introduce armffa command
  2022-03-29 15:16 [PATCH 0/6] introduce Arm FF-A support abdellatif.elkhlifi
  2022-03-29 15:16 ` [PATCH 1/6] arm_ffa: introduce Arm FF-A low-level driver abdellatif.elkhlifi
@ 2022-03-29 15:16 ` abdellatif.elkhlifi
  2023-07-27  5:51   ` Heinrich Schuchardt
  2022-03-29 15:16 ` [PATCH 3/6] arm_ffa: introduce the FF-A Sandbox driver abdellatif.elkhlifi
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-03-29 15:16 UTC (permalink / raw)
  To: u-boot; +Cc: nd, trini, Abdellatif El Khlifi

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

Provide armffa command showcasing the use of the FF-A driver

The armffa command allows to query secure partitions data from
the secure world and exchanging messages with the partitions.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
---
 MAINTAINERS             |   1 +
 cmd/Kconfig             |  10 ++
 cmd/Makefile            |   2 +
 cmd/armffa.c            | 266 ++++++++++++++++++++++++++++++++++++++++
 drivers/arm-ffa/Kconfig |   1 +
 5 files changed, 280 insertions(+)
 create mode 100644 cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index c5b608eb60..50ccd6a7ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -235,6 +235,7 @@ F:	include/configs/turris_*.h
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+F:	cmd/armffa.c
 F:	drivers/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/arm_ffa_helper.h
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 79219bcb74..de5bea1404 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -813,6 +813,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the Arm FF-A driver
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index ede634d731..2905ce63cf 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,8 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
 obj-$(CONFIG_CMD_AES) += aes.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..fcfc3a06bd
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <arm_ffa_helper.h>
+#include <asm/io.h>
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+
+/**
+ * do_ffa_get_singular_partition_info - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver helper function
+ * to retrieve the data.
+ * The input UUID string is expected to be in big endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_get_singular_partition_info(struct cmd_tbl *cmdtp, int flag, int argc,
+					      char *const argv[])
+{
+	struct ffa_interface_data func_data = {0};
+	u32 count = 0;
+	int ret;
+	union ffa_partition_uuid service_uuid = {0};
+	struct ffa_partition_info *parts_info;
+	u32 info_idx;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	if (ffa_uuid_str_to_bin(argv[0], (unsigned char *)&service_uuid)) {
+		ffa_err("Invalid UUID");
+		return -EINVAL;
+	}
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	func_data.data0_size = sizeof(service_uuid);
+	func_data.data0 = &service_uuid;
+	func_data.data1_size = sizeof(count);
+	func_data.data1 = &count;
+
+	ret = ffa_helper_get_partitions_info(&func_data);
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		ffa_err("Failure in querying partitions count (error code: %d)", ret);
+		return ret;
+	}
+
+	if (!count) {
+		ffa_info("No secure partition found");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	ffa_info("Pre-allocating %d partition(s) info structures", count);
+
+	func_data.data1_size = count * sizeof(struct ffa_partition_info);
+	func_data.data1 = parts_info;
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+	ret = ffa_helper_get_partitions_info(&func_data);
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		ffa_err("Failure in querying partition(s) info (error code: %d)", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * SPs found , show the partition information
+	 */
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		ffa_info("Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x",
+			 parts_info[info_idx].id,
+			 parts_info[info_idx].exec_ctxt,
+			 parts_info[info_idx].properties);
+	}
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * do_ffa_msg_send_direct_req - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function sends data to the secure partition which the ID is provided
+ * as an argument. The function uses the arm_ffa driver helper function
+ * to send data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int  do_ffa_msg_send_direct_req(struct cmd_tbl *cmdtp, int flag, int argc,
+				char *const argv[])
+{
+	struct ffa_interface_data func_data = {0};
+	struct ffa_send_direct_data msg = {0};
+	u32 pattern = 0xaabbccd0;
+	u16 part_id;
+	int ret;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	errno = 0;
+	part_id = strtoul(argv[0], NULL, 16);
+
+	if (errno) {
+		ffa_err("Invalid partition ID");
+		return -EINVAL;
+	}
+
+	/*
+	 * telling the driver which partition to use
+	 */
+	func_data.data0_size = sizeof(part_id);
+	func_data.data0 = &part_id;
+
+	/*
+	 * filling the message data
+	 */
+	msg.a3 = ++pattern;
+	msg.a4 = ++pattern;
+	msg.a5 = ++pattern;
+	msg.a6 = ++pattern;
+	msg.a7 = ++pattern;
+	func_data.data1_size = sizeof(msg);
+	func_data.data1 = &msg;
+
+	ret = ffa_helper_msg_send_direct_req(&func_data);
+	if (ret == FFA_ERR_STAT_SUCCESS) {
+		u8 cnt;
+
+		ffa_info("SP response:\n[LSB]");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u32);
+		     cnt++)
+			ffa_info("0x%x", ((u32 *)&msg)[cnt]);
+	} else {
+		ffa_err("Sending direct request error (%d)", ret);
+	}
+
+	return ret;
+}
+
+/**
+ *do_ffa_dev_list - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the devices belonging to the UCLASS_FFA
+ * class. Currently, one device is expected to show up: the arm_ffa device
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_dev_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev = NULL;
+	int i, ret;
+
+	ffa_info("arm_ffa uclass entries:");
+
+	for (i = 0, ret = uclass_first_device(UCLASS_FFA, &dev);
+	     dev;
+	     ret = uclass_next_device(&dev), i++) {
+		if (ret)
+			break;
+
+		ffa_info("entry %d - instance %08x, ops %08x, plat %08x",
+			 i,
+			 (u32)map_to_sysmem(dev),
+			 (u32)map_to_sysmem(dev->driver->ops),
+			 (u32)map_to_sysmem(dev_get_plat(dev)));
+	}
+
+	return cmd_process_error(cmdtp, ret);
+}
+
+static struct cmd_tbl armffa_commands[] = {
+	U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_get_singular_partition_info, "", ""),
+	U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_msg_send_direct_req, "", ""),
+	U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_dev_list, "", ""),
+};
+
+/**
+ * do_armffa - the armffa command main function
+ * @cmdtp:	Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function identifies which armffa subcommand to run.
+ * Then, it makes sure the arm_ffa device is probed and
+ * ready for use.
+ * Then, it runs the subcommand.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct cmd_tbl *armffa_cmd;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
+
+	argc -= 2;
+	argv += 2;
+
+	if (!armffa_cmd || argc > armffa_cmd->maxargs)
+		return CMD_RET_USAGE;
+
+	ret = ffa_helper_init_device();
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return cmd_process_error(cmdtp, ret);
+
+	ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
+
+	return cmd_process_error(armffa_cmd, ret);
+}
+
+U_BOOT_CMD(armffa, 4, 1, do_armffa,
+	   "Arm FF-A operations test command",
+	   "getpart <partition UUID>\n"
+	   "	 - lists the partition(s) info\n"
+	   "ping <partition ID>\n"
+	   "	 - sends a data pattern to the specified partition\n"
+	   "devlist\n"
+	   "	 - displays the arm_ffa device info\n");
diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
index e503dfaebf..7b7cfe26b1 100644
--- a/drivers/arm-ffa/Kconfig
+++ b/drivers/arm-ffa/Kconfig
@@ -4,6 +4,7 @@ config ARM_FFA_TRANSPORT
 	bool "Enable Arm Firmware Framework for Armv8-A driver"
 	depends on DM && ARM64
 	select ARM_SMCCC if ARM64
+	select CMD_ARMFFA
 	select LIB_UUID
 	select ARM_FFA_TRANSPORT_HELPERS
 	help
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH 3/6] arm_ffa: introduce the FF-A Sandbox driver
  2022-03-29 15:16 [PATCH 0/6] introduce Arm FF-A support abdellatif.elkhlifi
  2022-03-29 15:16 ` [PATCH 1/6] arm_ffa: introduce Arm FF-A low-level driver abdellatif.elkhlifi
  2022-03-29 15:16 ` [PATCH 2/6] arm_ffa: introduce armffa command abdellatif.elkhlifi
@ 2022-03-29 15:16 ` abdellatif.elkhlifi
  2022-03-29 15:16 ` [PATCH 4/6] arm_ffa: introduce Sandbox test cases for UCLASS_FFA abdellatif.elkhlifi
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-03-29 15:16 UTC (permalink / raw)
  To: u-boot; +Cc: nd, trini, Abdellatif El Khlifi

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

Provide a Sandbox driver to emulate the FF-A ABIs

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

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

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
---
 MAINTAINERS                           |   2 +
 arch/sandbox/dts/sandbox.dtsi         |  10 +
 arch/sandbox/dts/test.dts             |  10 +
 common/board_r.c                      |   2 +-
 configs/sandbox64_defconfig           |   2 +
 configs/sandbox_defconfig             |   2 +
 doc/arch/sandbox.rst                  |   1 +
 drivers/arm-ffa/Kconfig               |   8 +-
 drivers/arm-ffa/Makefile              |   1 +
 drivers/arm-ffa/arm-ffa-uclass.c      |  51 +-
 drivers/arm-ffa/core.c                |  94 +++-
 drivers/arm-ffa/sandbox.c             | 735 ++++++++++++++++++++++++++
 drivers/arm-ffa/sandbox_arm_ffa_prv.h | 128 +++++
 include/arm_ffa.h                     |   9 +-
 include/sandbox_arm_ffa.h             |  31 ++
 include/sandbox_arm_ffa_helper.h      |  26 +
 lib/arm-ffa/Makefile                  |   1 +
 lib/arm-ffa/arm_ffa_helper.c          |   6 +-
 lib/arm-ffa/sandbox_arm_ffa_helper.c  |  23 +
 lib/efi_loader/efi_boottime.c         |   4 +-
 20 files changed, 1102 insertions(+), 44 deletions(-)
 create mode 100644 drivers/arm-ffa/sandbox.c
 create mode 100644 drivers/arm-ffa/sandbox_arm_ffa_prv.h
 create mode 100644 include/sandbox_arm_ffa.h
 create mode 100644 include/sandbox_arm_ffa_helper.h
 create mode 100644 lib/arm-ffa/sandbox_arm_ffa_helper.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 50ccd6a7ba..84524d7caf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -239,6 +239,8 @@ F:	cmd/armffa.c
 F:	drivers/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/arm_ffa_helper.h
+F:	include/sandbox_arm_ffa.h
+F:	include/sandbox_arm_ffa_helper.h
 F:	lib/arm-ffa/
 
 ARM FREESCALE IMX
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index 66b813faad..523ffcc27d 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -416,6 +416,16 @@
 	sandbox_tee {
 		compatible = "sandbox,tee";
 	};
+
+	arm_ffa {
+		compatible = "arm,ffa";
+		method = "smc";
+	};
+
+	sandbox_arm_ffa {
+		compatible = "sandbox,ffa";
+		method = "smc";
+	};
 };
 
 &cros_ec {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 3d206fdb3c..2c638af042 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1598,6 +1598,16 @@
 			compatible = "sandbox,regmap_test";
 		};
 	};
+
+	arm_ffa {
+		compatible = "arm,ffa";
+		method = "smc";
+	};
+
+	sandbox_arm_ffa {
+		compatible = "sandbox,ffa";
+		method = "smc";
+	};
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/common/board_r.c b/common/board_r.c
index 7866ec3ad5..3b82f74bb0 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -775,7 +775,7 @@ static init_fnc_t init_sequence_r[] = {
 	INIT_FUNC_WATCHDOG_RESET
 	initr_net,
 #endif
-#ifdef CONFIG_ARM_FFA_TRANSPORT
+#if defined(CONFIG_ARM_FFA_TRANSPORT) && !defined(CONFIG_SANDBOX_FFA)
 	ffa_helper_init_device,
 #endif
 #ifdef CONFIG_POST
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 40d1422a37..301c6f320f 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -252,3 +252,5 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
+CONFIG_SANDBOX_FFA=y
\ No newline at end of file
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 0f43101ab5..a2f273056f 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -324,3 +324,5 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
+CONFIG_SANDBOX_FFA=y
\ No newline at end of file
diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst
index f8804e1f41..7cb5ea307c 100644
--- a/doc/arch/sandbox.rst
+++ b/doc/arch/sandbox.rst
@@ -203,6 +203,7 @@ Supported Drivers
 
 U-Boot sandbox supports these emulations:
 
+- Arm FF-A
 - Block devices
 - Chrome OS EC
 - GPIO
diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
index 7b7cfe26b1..61103daa42 100644
--- a/drivers/arm-ffa/Kconfig
+++ b/drivers/arm-ffa/Kconfig
@@ -2,7 +2,7 @@
 
 config ARM_FFA_TRANSPORT
 	bool "Enable Arm Firmware Framework for Armv8-A driver"
-	depends on DM && ARM64
+	depends on DM && (ARM64 || SANDBOX)
 	select ARM_SMCCC if ARM64
 	select CMD_ARMFFA
 	select LIB_UUID
@@ -24,3 +24,9 @@ config ARM_FFA_TRANSPORT
 	  entity to communicate with. FF-A communication is handled by
 	  one device and one instance. This device takes care of
 	  all the interactions between Normal world and Secure World.
+
+config SANDBOX_FFA
+	bool "FF-A Sandbox driver"
+	depends on ARM_FFA_TRANSPORT && SANDBOX
+	help
+	  This emulates the FF-A handling under Sandbox and allows to test the FF-A driver
diff --git a/drivers/arm-ffa/Makefile b/drivers/arm-ffa/Makefile
index 7bc9a336a9..df1cfe6ef0 100644
--- a/drivers/arm-ffa/Makefile
+++ b/drivers/arm-ffa/Makefile
@@ -4,3 +4,4 @@
 #
 
 obj-y += arm-ffa-uclass.o core.o
+obj-$(CONFIG_SANDBOX_FFA) += sandbox.o
diff --git a/drivers/arm-ffa/arm-ffa-uclass.c b/drivers/arm-ffa/arm-ffa-uclass.c
index 0bf661d397..a5945afb9d 100644
--- a/drivers/arm-ffa/arm-ffa-uclass.c
+++ b/drivers/arm-ffa/arm-ffa-uclass.c
@@ -11,6 +11,10 @@
 #include <log.h>
 #include <asm/global_data.h>
 
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+#include <sandbox_arm_ffa.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 UCLASS_DRIVER(ffa) = {
@@ -42,18 +46,42 @@ int __ffa_runtime ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *fu
 	return ffa_device_get_ops()->invoke_func(func_id, func_data);
 }
 
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+
 /**
- * ffa_init_device - probes the arm_ffa device
+ * sandbox_ffa_get_invoke_func - performs a call to the Sandbox FF-A driver dispatcher
+ * @func_id:	The FF-A function to be queried
+ * @func_data:  Pointer to the query arguments
+ *				container structure.
+ *
+ * This function passes the FF-A function ID to be queried during sandbox test cases
+ *  and its arguments to the Sandbox FF-A driver dispatcher.
+ * This function is called by the Sandbox FF-A helper function.
+ *
+ * Return:
  *
- * This boot time function makes sure the arm_ffa device is probed
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int sandbox_ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *func_data)
+{
+	if (!sandbox_ffa_device_get_ops()->invoke_func)
+		return -EINVAL;
+
+	return sandbox_ffa_device_get_ops()->invoke_func(func_id, func_data);
+}
+#endif
+
+/**
+ * ffa_init_device - probes the arm_ffa and sandbox_arm_ffa devices
+ *
+ * This boot time function makes sure the arm_ffa and sandbox_arm_ffa devices are probed
  * and ready for use.
  * This function is called automatically at initcalls
  * level (after u-boot relocation).
  *
- * Arm FF-A transport is implemented through a single u-boot
- * device (arm_ffa). So, there is only one device belonging to UCLASS_FFA.
- * All FF-A clients should use the arm_ffa device to use the FF-A
- * transport.
+ * Arm FF-A transport is implemented through arm_ffa u-boot device managing the FF-A
+ * 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:
  *
@@ -61,5 +89,14 @@ int __ffa_runtime ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *fu
  */
 int ffa_init_device(void)
 {
-	return ffa_get_device();
+	int ret;
+
+	ret = ffa_get_device();
+
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+	if (ret == FFA_ERR_STAT_SUCCESS)
+		ret = sandbox_ffa_get_device();
+#endif
+
+	return ret;
 }
diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c
index 9d0dab1d36..a4d9c08482 100644
--- a/drivers/arm-ffa/core.c
+++ b/drivers/arm-ffa/core.c
@@ -5,6 +5,11 @@
  */
 
 #include "arm_ffa_prv.h"
+
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+#include "sandbox_arm_ffa_prv.h"
+#endif
+
 #include <asm/global_data.h>
 #include <asm/io.h>
 #include <common.h>
@@ -82,8 +87,10 @@ static int ffa_get_version(void)
 
 	FFA_DECLARE_ARGS;
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	a0 = FFA_VERSION;
 	a1 = FFA_VERSION_1_0;
@@ -126,8 +133,10 @@ static int ffa_get_endpoint_id(void)
 {
 	FFA_DECLARE_ARGS;
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	a0 = FFA_ID_GET;
 
@@ -200,8 +209,10 @@ static int ffa_get_rxtx_map_features(void)
 {
 	FFA_DECLARE_ARGS;
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	a0 = FFA_FEATURES;
 	a1 = FFA_RXTX_MAP;
@@ -427,8 +438,10 @@ static int ffa_map_rxtx_buffers(size_t buf_4k_pages)
 
 	FFA_DECLARE_ARGS;
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	ret = ffa_alloc_rxtx_buffers(buf_4k_pages);
 	if (ret != FFA_ERR_STAT_SUCCESS)
@@ -496,8 +509,10 @@ static int ffa_unmap_rxtx_buffers(void)
 {
 	FFA_DECLARE_ARGS;
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	a0 = FFA_RXTX_UNMAP;
 	a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id);
@@ -508,11 +523,12 @@ static int ffa_unmap_rxtx_buffers(void)
 	case FFA_ERROR:
 	{
 		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
-			panic("[FFA] FFA_RXTX_UNMAP is not implemented at this FF-A instance\n");
+			ffa_panic("FFA_RXTX_UNMAP is not implemented at this FF-A instance\n");
 		else if (((int)res.a2) == FFA_ERR_STAT_INVALID_PARAMETERS)
-			panic("[FFA] There is no buffer pair registered on behalf of the caller\n");
+			ffa_panic("There is no buffer pair registered on behalf of the caller\n");
 		else
-			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
+			ffa_panic("Undefined error (%d)\n", ((int)res.a2));
+		return -ENODEV;
 	}
 	case FFA_SUCCESS:
 	{
@@ -520,19 +536,24 @@ static int ffa_unmap_rxtx_buffers(void)
 		int ret;
 
 		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
-		if (ret != FFA_ERR_STAT_SUCCESS)
-			panic("[FFA] RX/TX buffers unmapped but failure in getting pages count\n");
+		if (ret != FFA_ERR_STAT_SUCCESS) {
+			ffa_panic("RX/TX buffers unmapped but failure in getting pages count\n");
+			return -ENODEV;
+		}
 
 		ret = ffa_free_rxtx_buffers(buf_4k_pages);
-		if (ret != FFA_ERR_STAT_SUCCESS)
-			panic("[FFA] RX/TX buffers unmapped but failure in freeing the memory\n");
+		if (ret != FFA_ERR_STAT_SUCCESS) {
+			ffa_panic("RX/TX buffers unmapped but failure in freeing the memory\n");
+			return -ENODEV;
+		}
 
 		ffa_info("RX/TX buffers unmapped and memory freed");
 
 		return FFA_ERR_STAT_SUCCESS;
 	}
 	default:
-		panic("[FFA] Undefined response function (0x%lx)", res.a0);
+		ffa_panic("Undefined response function (0x%lx)", res.a0);
+		return -ENODEV;
 	}
 }
 
@@ -550,8 +571,10 @@ static int ffa_release_rx_buffer(void)
 {
 	FFA_DECLARE_ARGS;
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	a0 = FFA_RX_RELEASE;
 
@@ -561,17 +584,19 @@ static int ffa_release_rx_buffer(void)
 	case FFA_ERROR:
 	{
 		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
-			panic("[FFA] FFA_RX_RELEASE is not implemented at this FF-A instance\n");
+			ffa_panic("FFA_RX_RELEASE is not implemented at this FF-A instance\n");
 		else if (((int)res.a2) == FFA_ERR_STAT_DENIED)
-			panic("[FFA] Caller did not have ownership of the RX buffer\n");
+			ffa_panic("Caller did not have ownership of the RX buffer\n");
 		else
-			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
+			ffa_panic("Undefined error (%d)\n", ((int)res.a2));
+		return -ENODEV;
 	}
 	case FFA_SUCCESS:
 		return FFA_ERR_STAT_SUCCESS;
 
 	default:
-		panic("[FFA] Undefined response function (0x%lx)\n", res.a0);
+		ffa_panic("Undefined response function (0x%lx)\n", res.a0);
+		return -ENODEV;
 	}
 }
 
@@ -763,8 +788,10 @@ static int ffa_query_partitions_info(union ffa_partition_uuid *part_uuid,
 	unsigned long a7 = 0;
 	struct arm_smccc_res res = {0};
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	a0 = FFA_PARTITION_INFO_GET;
 
@@ -840,7 +867,7 @@ static int ffa_query_partitions_info(union ffa_partition_uuid *part_uuid,
 		ret = ffa_release_rx_buffer();
 
 		if (!part_uuid && !res.a2) {
-			ffa_err("[FFA] no partition installed in the system");
+			ffa_err("no partition installed in the system");
 			return -ENODEV;
 		}
 
@@ -931,8 +958,10 @@ static int ffa_get_partitions_info(struct ffa_interface_data *func_data)
 		return -EINVAL;
 	}
 
-	if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs)
-		panic("[FFA] No partition installed\n");
+	if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs) {
+		ffa_panic("No partition installed\n");
+		return -ENODEV;
+	}
 
 	if (func_data->data0_size == sizeof(union ffa_partition_uuid) &&
 	    func_data->data0 &&
@@ -1170,6 +1199,7 @@ static int __ffa_runtime ffa_msg_send_direct_req(struct ffa_interface_data
 			/* Undefined error */
 			return -ENXIO;
 		}
+		return -ENODEV;
 	}
 	case FFA_SUCCESS:
 
@@ -1247,7 +1277,13 @@ static int ffa_init_private_data(struct udevice *dev)
 	ffa_priv_data.conduit = pdata->conduit;
 
 	if (ffa_priv_data.conduit == FFA_CONDUIT_SMC) {
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+		ffa_priv_data.invoke_ffa_fn = sandbox_arm_ffa_smccc_smc;
+		ffa_info("Using SMC emulation");
+#else
 		ffa_priv_data.invoke_ffa_fn = arm_ffa_smccc_smc;
+#endif
+
 	} else {
 		ffa_err("Undefined FF-A conduit (%d)", ffa_priv_data.conduit);
 		return -EINVAL;
diff --git a/drivers/arm-ffa/sandbox.c b/drivers/arm-ffa/sandbox.c
new file mode 100644
index 0000000000..fcabd4b59b
--- /dev/null
+++ b/drivers/arm-ffa/sandbox.c
@@ -0,0 +1,735 @@
+// 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 <linux/errno.h>
+#include <linux/sizes.h>
+#include <mapmem.h>
+#include <string.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * The device private data structure containing all the emulated secure world data
+ */
+static struct sandbox_ffa_prvdata  sandbox_ffa_priv_data = {0};
+
+/* The partitions (SPs) table */
+static struct ffa_partition_desc sandbox_partitions[SANDBOX_PARTITIONS_CNT] = {
+	{
+		.info = { .id = 0x1245, .exec_ctxt = 0x5687, .properties = 0x89325621 },
+		.UUID = { .bytes = {SANDBOX_SERVICE1_UUID_DATA}}
+	},
+	{
+		.info = { .id = 0x9836, .exec_ctxt = 0x9587, .properties = 0x45325621 },
+		.UUID = { .bytes = {SANDBOX_SERVICE2_UUID_DATA}}
+	},
+	{
+		.info = { .id = 0x6452, .exec_ctxt = 0x7687, .properties = 0x23325621 },
+		.UUID = { .bytes = {SANDBOX_SERVICE1_UUID_DATA}}
+	},
+	{
+		.info = { .id = 0x7814, .exec_ctxt = 0x1487, .properties = 0x70325621 },
+		.UUID = { .bytes = {SANDBOX_SERVICE2_UUID_DATA}}
+	}
+
+};
+
+/*
+ * Driver functions
+ */
+
+/**
+ * sandbox_ffa_get_device - probes the sandbox_arm_ffa device
+ *
+ * This function makes sure the sandbox_arm_ffa device is probed
+ * and ready for use. This is done using uclass_get_device.
+ * The arm_ffa driver belongs to UCLASS_FFA.
+ * This function should be called before using the driver.
+ *
+ * sandbox_arm_ffa depends on arm_ffa device. This dependency is
+ * handled by ffa_init_device function. arm_ffa is probed first then
+ * it probes sandbox_arm_ffa using sandbox_ffa_get_device.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int sandbox_ffa_get_device(void)
+{
+	int ret;
+	int devnum = 1;
+
+	if (sandbox_ffa_priv_data.dev)
+		return FFA_ERR_STAT_SUCCESS;
+
+	/*
+	 * searching and probing the device
+	 */
+	ret = uclass_get_device(UCLASS_FFA, devnum, &sandbox_ffa_priv_data.dev);
+	if (ret) {
+		ffa_err("[Sandbox] Can not find the FF-A Sandbox device");
+		sandbox_ffa_priv_data.dev = NULL;
+		return -ENODEV;
+	}
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_version - Emulated FFA_VERSION handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_VERSION FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_version)
+{
+	sandbox_ffa_priv_data.fwk_version = FFA_VERSION_1_0;
+	res->a0 = sandbox_ffa_priv_data.fwk_version;
+
+	/* w1-w7 MBZ */
+	memset(FFA_W1W7_MBZ_REG_START, 0, FFA_W1W7_MBZ_CNT * sizeof(unsigned long));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_id_get - Emulated FFA_ID_GET handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_ID_GET FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_id_get)
+{
+	res->a0 = FFA_SUCCESS;
+	res->a1 = 0;
+
+	sandbox_ffa_priv_data.id = NS_PHYS_ENDPOINT_ID;
+	res->a2 = sandbox_ffa_priv_data.id;
+
+	/* w3-w7 MBZ */
+	memset(FFA_W3_MBZ_REG_START, 0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_features - Emulated FFA_FEATURES handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_FEATURES FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_features)
+{
+	switch (a1) {
+	case FFA_RXTX_MAP:
+	{
+		res->a0 = FFA_SUCCESS;
+		res->a2 = RXTX_BUFFERS_MIN_SIZE;
+		res->a3 = 0;
+		/* w4-w7 MBZ */
+		memset(FFA_W4W7_MBZ_REG_START,
+		       0, FFA_W4W7_MBZ_CNT * sizeof(unsigned long));
+		break;
+	}
+	default:
+	{
+		res->a0 = FFA_ERROR;
+		res->a2 = FFA_ERR_STAT_NOT_SUPPORTED;
+		/* w3-w7 MBZ */
+		memset(FFA_W3_MBZ_REG_START,
+		       0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+		ffa_err("[Sandbox] FF-A interface 0x%lx not implemented", a1);
+	}
+	}
+
+	res->a1 = 0;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_partition_info_get - Emulated FFA_PARTITION_INFO_GET handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_PARTITION_INFO_GET FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_partition_info_get)
+{
+	struct ffa_partition_info *rxbuf_desc_info = NULL;
+	u32 descs_cnt;
+	u32 descs_size_bytes;
+
+	res->a0 = FFA_ERROR;
+
+	if (!sandbox_ffa_priv_data.pair.rxbuf) {
+		res->a2 = FFA_ERR_STAT_DENIED;
+		goto cleanup;
+	}
+
+	if (sandbox_ffa_priv_data.pair_info.rxbuf_owned) {
+		res->a2 = FFA_ERR_STAT_BUSY;
+		goto cleanup;
+	}
+
+	if (!sandbox_ffa_priv_data.partitions.descs) {
+		sandbox_ffa_priv_data.partitions.descs = sandbox_partitions;
+		sandbox_ffa_priv_data.partitions.count = SANDBOX_PARTITIONS_CNT;
+	}
+
+	descs_size_bytes = SANDBOX_PARTITIONS_CNT * sizeof(struct ffa_partition_desc);
+
+	/* Abort if the RX buffer size is smaller than the descriptors buffer size */
+	if ((sandbox_ffa_priv_data.pair_info.rxtx_buf_size * SZ_4K) < descs_size_bytes) {
+		res->a2 = FFA_ERR_STAT_NO_MEMORY;
+		goto cleanup;
+	}
+
+	rxbuf_desc_info = (struct ffa_partition_info *)sandbox_ffa_priv_data.pair.rxbuf;
+
+	/* No UUID specified. Return the information of all partitions */
+	if (!a1 && !a2 && !a3 && !a4) {
+		for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++)
+			*(rxbuf_desc_info++) =
+				sandbox_ffa_priv_data.partitions.descs[descs_cnt].info;
+
+		res->a0 = FFA_SUCCESS;
+		res->a2 = SANDBOX_PARTITIONS_CNT;
+		/* transfer ownership to the consumer: the non secure world */
+		sandbox_ffa_priv_data.pair_info.rxbuf_owned = 1;
+
+		goto cleanup;
+	}
+
+	/*
+	 * A UUID is specified. Return the information of all partitions matching
+	 * the UUID
+	 */
+
+	for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++)
+		if (a1 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].UUID.words.a1 &&
+		    a2 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].UUID.words.a2 &&
+		    a3 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].UUID.words.a3 &&
+		    a4 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].UUID.words.a4) {
+			*(rxbuf_desc_info++) =
+				sandbox_ffa_priv_data.partitions.descs[descs_cnt].info;
+		}
+
+	if (rxbuf_desc_info != ((struct ffa_partition_info *)sandbox_ffa_priv_data.pair.rxbuf)) {
+		res->a0 = FFA_SUCCESS;
+		/* store the partitions count */
+		res->a2 = (unsigned long)
+			(rxbuf_desc_info - (struct ffa_partition_info *)
+			 sandbox_ffa_priv_data.pair.rxbuf);
+
+		/* transfer ownership to the consumer: the non secure world */
+		sandbox_ffa_priv_data.pair_info.rxbuf_owned = 1;
+	} else {
+		res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS;
+	}
+
+cleanup:
+
+	ffa_err("[Sandbox] FFA_PARTITION_INFO_GET (%ld)", res->a2);
+
+	res->a1 = 0;
+
+	/* w3-w7 MBZ */
+	memset(FFA_W3_MBZ_REG_START, 0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_rxtx_map - Emulated FFA_RXTX_MAP handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_RXTX_MAP FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_rxtx_map)
+{
+	res->a0 = FFA_ERROR;
+
+	if (sandbox_ffa_priv_data.pair.txbuf && sandbox_ffa_priv_data.pair.rxbuf) {
+		res->a2 = FFA_ERR_STAT_DENIED;
+		goto feedback;
+	}
+
+	if (a3 >= RXTX_BUFFERS_MIN_PAGES && a1 && a2) {
+		sandbox_ffa_priv_data.pair.txbuf = a1;
+		sandbox_ffa_priv_data.pair.rxbuf = a2;
+		sandbox_ffa_priv_data.pair_info.rxtx_buf_size = a3;
+		sandbox_ffa_priv_data.pair_info.rxbuf_mapped = 1;
+		res->a0 = FFA_SUCCESS;
+		res->a2 = 0;
+		goto feedback;
+	}
+
+	if (!a1 || !a2)
+		res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS;
+	else
+		res->a2 = FFA_ERR_STAT_NO_MEMORY;
+
+	ffa_err("[Sandbox] error in FFA_RXTX_MAP arguments (%d)", (int)res->a2);
+
+feedback:
+
+	res->a1 = 0;
+
+	/* w3-w7 MBZ */
+	memset(FFA_W3_MBZ_REG_START,
+	       0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_rxtx_unmap - Emulated FFA_RXTX_UNMAP handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_RXTX_UNMAP FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_rxtx_unmap)
+{
+	res->a0 = FFA_ERROR;
+	res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS;
+
+	if (GET_NS_PHYS_ENDPOINT_ID(a1) != sandbox_ffa_priv_data.id)
+		goto feedback;
+
+	if (sandbox_ffa_priv_data.pair.txbuf && sandbox_ffa_priv_data.pair.rxbuf) {
+		sandbox_ffa_priv_data.pair.txbuf = 0;
+		sandbox_ffa_priv_data.pair.rxbuf = 0;
+		sandbox_ffa_priv_data.pair_info.rxtx_buf_size = 0;
+		sandbox_ffa_priv_data.pair_info.rxbuf_mapped = 0;
+		res->a0 = FFA_SUCCESS;
+		res->a2 = 0;
+		goto feedback;
+	}
+
+	ffa_err("[Sandbox] No buffer pair registered on behalf of the caller");
+
+feedback:
+
+	res->a1 = 0;
+
+	/* w3-w7 MBZ */
+	memset(FFA_W3_MBZ_REG_START,
+	       0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_rx_release - Emulated FFA_RX_RELEASE handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_RX_RELEASE FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_rx_release)
+{
+	if (!sandbox_ffa_priv_data.pair_info.rxbuf_owned) {
+		res->a0 = FFA_ERROR;
+		res->a2 = FFA_ERR_STAT_DENIED;
+	} else {
+		sandbox_ffa_priv_data.pair_info.rxbuf_owned = 0;
+		res->a0 = FFA_SUCCESS;
+		res->a2 = 0;
+	}
+
+	res->a1 = 0;
+
+	/* w3-w7 MBZ */
+	memset(FFA_W3_MBZ_REG_START,
+	       0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_sp_valid - Checks SP validity
+ * @part_id: partition ID to check
+ *
+ * This is the function searches the input ID in the descriptors table.
+ *
+ * Return:
+ *
+ * 1 on success (Partition found). Otherwise, failure
+ */
+int sandbox_ffa_sp_valid(u16 part_id)
+{
+	u32 descs_cnt;
+
+	for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++)
+		if (sandbox_ffa_priv_data.partitions.descs[descs_cnt].info.id == part_id)
+			return 1;
+
+	return 0;
+}
+
+/**
+ * sandbox_ffa_msg_send_direct_req - Emulated FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * Emulating interrupts is not supported. So, FFA_RUN and FFA_INTERRUPT are not supported.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_msg_send_direct_req)
+{
+	u16 part_id;
+
+	part_id = GET_DST_SP_ID(a1);
+
+	if ((GET_NS_PHYS_ENDPOINT_ID(a1) != sandbox_ffa_priv_data.id) ||
+	    !sandbox_ffa_sp_valid(part_id) ||
+		a2) {
+		res->a0 = FFA_ERROR;
+		res->a1 = 0;
+		res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS;
+
+		/* w3-w7 MBZ */
+		memset(FFA_W3_MBZ_REG_START,
+		       0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+
+		return FFA_ERR_STAT_SUCCESS;
+	}
+
+	res->a0 = FFA_MSG_SEND_DIRECT_RESP;
+
+	res->a1 = PREP_SRC_SP_ID(part_id) |
+		PREP_NS_PHYS_ENDPOINT_ID(sandbox_ffa_priv_data.id);
+
+	res->a2 = 0;
+
+	/*
+	 * return 0xff bytes as a response
+	 */
+	res->a3 = 0xffffffff;
+	res->a4 = 0xffffffff;
+	res->a5 = 0xffffffff;
+	res->a6 = 0xffffffff;
+	res->a7 = 0xffffffff;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_get_prv_data - Returns the pointer to FF-A core pivate data
+ * @func_data:  Pointer to the FF-A function arguments container structure
+ *
+ * This is the handler that returns the address of the FF-A core pivate data.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int sandbox_ffa_get_prv_data(struct ffa_interface_data *func_data)
+{
+	if (!func_data)
+		return -EINVAL;
+
+	if (!func_data->data0 || func_data->data0_size != sizeof(struct ffa_prvdata **))
+		return -EINVAL;
+
+	if (!func_data->data1 || func_data->data1_size != sizeof(struct sandbox_ffa_prvdata **))
+		return -EINVAL;
+
+	*((struct ffa_prvdata **)func_data->data0) = &ffa_priv_data;
+	*((struct sandbox_ffa_prvdata **)func_data->data1) = &sandbox_ffa_priv_data;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_get_rxbuf_flags - Reading the mapping/ownership flags
+ * @queried_func_id:	The FF-A function to be queried
+ * @func_data:  Pointer to the FF-A function arguments container structure
+ *
+ * This is the handler that queries the status flags of the following emulated ABIs:
+ * FFA_RXTX_MAP, FFA_RXTX_UNMAP, FFA_RX_RELEASE
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int sandbox_ffa_get_rxbuf_flags(u32 queried_func_id, struct ffa_interface_data *func_data)
+{
+	if (!func_data)
+		return -EINVAL;
+
+	if (!func_data->data0 || func_data->data0_size != sizeof(u8))
+		return -EINVAL;
+
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+	case FFA_RXTX_UNMAP:
+		*((u8 *)func_data->data0) = sandbox_ffa_priv_data.pair_info.rxbuf_mapped;
+		return FFA_ERR_STAT_SUCCESS;
+	case FFA_RX_RELEASE:
+		*((u8 *)func_data->data0) = sandbox_ffa_priv_data.pair_info.rxbuf_owned;
+		return FFA_ERR_STAT_SUCCESS;
+	default:
+		ffa_err("[Sandbox] The querried  FF-A interface flag (%d) undefined",
+			queried_func_id);
+		return -EINVAL;
+	}
+}
+
+/**
+ * invoke_sandbox_ffa_drv_api - The driver dispatcher function
+ * @queried_func_id:	The FF-A function to be queried
+ * @func_data:  Pointer to the FF-A function arguments container structure
+ *
+ * The dispatcher function that selects the handler that queries the
+ * status of FF-A ABIs given in the input argument.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int invoke_sandbox_ffa_drv_api(u32 queried_func_id, struct ffa_interface_data *func_data)
+{
+	switch (queried_func_id) {
+	case FFA_VERSION:
+	case FFA_ID_GET:
+	case FFA_FEATURES:
+		return sandbox_ffa_get_prv_data(func_data);
+	case FFA_RXTX_MAP:
+	case FFA_RXTX_UNMAP:
+	case FFA_RX_RELEASE:
+		return sandbox_ffa_get_rxbuf_flags(queried_func_id, func_data);
+	default:
+		ffa_err("[Sandbox] The querried  FF-A interface (%d) undefined", queried_func_id);
+		return -EINVAL;
+	}
+}
+
+/**
+ * sandbox_ffa_init_prv_data_from_dtb - init private data fields from DTB
+ * @dev:	the sandbox_arm_ffa device
+ *
+ * The value of the conduit field in the private data structure is read  from the DTB.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int sandbox_ffa_init_prv_data_from_dtb(struct udevice *dev)
+{
+	struct ffa_pdata *pdata = dev_get_plat(dev);
+
+	sandbox_ffa_priv_data.conduit = pdata->conduit;
+
+	if (sandbox_ffa_priv_data.conduit != FFA_CONDUIT_SMC) {
+		ffa_err("[Sandbox] Undefined FF-A conduit (%d)", sandbox_ffa_priv_data.conduit);
+		return -EINVAL;
+	}
+
+	ffa_info("[Sandbox] Conduit is SMC");
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_arm_ffa_smccc_smc - FF-A SMC call emulation
+ * @dev:	the SMC arguments to be passed to the FF-A ABI
+ *
+ * Sandbox driver emulates the FF-A ABIs SMC call using this function.
+ * The emulated FF-A ABI is identified and invoked.
+ * FF-A emulation is based on the FF-A specification 1.0
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure.
+ * FF-A protocol error codes are returned using the registers arguments as described
+ * by the specification
+ */
+void sandbox_arm_ffa_smccc_smc(unsigned long a0, unsigned long a1,
+			       unsigned long a2, unsigned long a3, unsigned long a4,
+			       unsigned long a5, unsigned long a6, unsigned long a7,
+			       struct arm_smccc_res *res)
+{
+	int ret = FFA_ERR_STAT_SUCCESS;
+
+	switch (a0) {
+	case FFA_VERSION:
+		ret = sandbox_ffa_version(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_PARTITION_INFO_GET:
+		ret = sandbox_ffa_partition_info_get(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_RXTX_UNMAP:
+		ret = sandbox_ffa_rxtx_unmap(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_MSG_SEND_DIRECT_REQ:
+		ret = sandbox_ffa_msg_send_direct_req(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_ID_GET:
+		ret = sandbox_ffa_id_get(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_FEATURES:
+		ret = sandbox_ffa_features(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_RXTX_MAP:
+		ret = sandbox_ffa_rxtx_map(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_RX_RELEASE:
+		ret = sandbox_ffa_rx_release(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	default:
+		ffa_err("[Sandbox] Undefined FF-A interface (0x%x)", (unsigned int)a0);
+	}
+
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		ffa_err("[Sandbox] FF-A ABI internal failure  (%d)", ret);
+}
+
+/**
+ * sandbox_ffa_bind - The driver bind function
+ * @dev:	the arm_ffa device
+ *
+ * Called when the driver is bound with the device based on the DTB node.
+ * The private data structure is cleared before use.
+ * This makes sure that when the device added/removed  multiple times the previous
+ * private structure is cleared.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS
+ */
+static int sandbox_ffa_bind(struct udevice *dev)
+{
+	memset(&sandbox_ffa_priv_data, 0, sizeof(sandbox_ffa_priv_data));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_probe - The driver probe function
+ * @dev:	the sandbox_arm_ffa device
+ *
+ * Probing is triggered by the uclass device discovery.
+ * At probe level the device tree conduit in the private structure
+ * is read from the DTB.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int sandbox_ffa_probe(struct udevice *dev)
+{
+	return sandbox_ffa_init_prv_data_from_dtb(dev);
+}
+
+/**
+ * sandbox_ffa_of_to_plat - Reads the device tree node
+ * @dev:	the sandbox_arm_ffa device
+ *
+ * This function reads data from the device tree node and populates
+ * the platform data structure
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int sandbox_ffa_of_to_plat(struct udevice *dev)
+{
+	struct ffa_pdata *pdata = dev_get_plat(dev);
+	const char *conduit;
+
+	conduit = dev_read_string(dev, "method");
+
+	if (!conduit) {
+		ffa_err("[Sandbox] Failure to read the conduit from device tree");
+		return -EINVAL;
+	}
+
+	if (strcmp("smc", conduit)) {
+		ffa_err("[Sandbox] Unsupported conduit");
+		return -EINVAL;
+	}
+
+	pdata->conduit = FFA_CONDUIT_SMC;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_drv_ops - The driver operations  structure
+ * @invoke_func:	The driver dispatcher
+ */
+struct ffa_ops  sandbox_ffa_drv_ops = {
+	.invoke_func = invoke_sandbox_ffa_drv_api
+};
+
+/**
+ * sandbox_ffa_device_get_ops - driver operations getter
+ *
+ * Return:
+ * This function returns a pointer to the driver operations structure
+ */
+const struct ffa_ops *sandbox_ffa_device_get_ops(void)
+{
+	return &sandbox_ffa_drv_ops;
+}
+
+/**
+ * Defining the device tree compatible string
+ */
+static const struct udevice_id sandbox_ffa_match_id[] = {
+	{"sandbox,ffa", 0},
+	{},
+};
+
+/**
+ * Declaring the sandbox_arm_ffa driver under UCLASS_FFA
+ */
+U_BOOT_DRIVER(sandbox_arm_ffa) = {
+	.name		= "sandbox_arm_ffa",
+	.of_match	= sandbox_ffa_match_id,
+	.id		= UCLASS_FFA,
+	.of_to_plat	= sandbox_ffa_of_to_plat,
+	.probe		= sandbox_ffa_probe,
+	.bind		= sandbox_ffa_bind,
+	.plat_auto	= sizeof(struct ffa_pdata),
+};
diff --git a/drivers/arm-ffa/sandbox_arm_ffa_prv.h b/drivers/arm-ffa/sandbox_arm_ffa_prv.h
new file mode 100644
index 0000000000..9f5085f098
--- /dev/null
+++ b/drivers/arm-ffa/sandbox_arm_ffa_prv.h
@@ -0,0 +1,128 @@
+/* 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"
+
+/*
+ * This header is private. It is exclusively used by the Sandbox FF-A driver
+ */
+
+/* Non-secure physical FF-A instance */
+#define NS_PHYS_ENDPOINT_ID (0)
+
+#define GET_NS_PHYS_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define GET_NS_PHYS_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_NS_PHYS_ENDPOINT_ID_MASK, (x))))
+
+/* Helper macro for reading the destination partition ID */
+#define GET_DST_SP_ID_MASK		GENMASK(15, 0)
+#define GET_DST_SP_ID(x)		\
+			((u16)(FIELD_GET(GET_DST_SP_ID_MASK, (x))))
+
+/* Helper macro for setting the source partition ID */
+#define PREP_SRC_SP_ID_MASK		GENMASK(31, 16)
+#define PREP_SRC_SP_ID(x)		\
+			(FIELD_PREP(PREP_SRC_SP_ID_MASK, (x)))
+
+/* Helper macro for setting the destination endpoint ID */
+#define PREP_NS_PHYS_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_NS_PHYS_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_NS_PHYS_ENDPOINT_ID_MASK, (x)))
+
+/*  RX/TX buffers minimum size */
+#define RXTX_BUFFERS_MIN_SIZE (RXTX_4K)
+#define RXTX_BUFFERS_MIN_PAGES (1)
+
+/* MBZ registers info */
+
+/* w1-w7 MBZ */
+#define FFA_W1W7_MBZ_CNT (7)
+#define FFA_W1W7_MBZ_REG_START (&res->a1)
+
+/* w4-w7 MBZ */
+#define FFA_W4W7_MBZ_CNT (4)
+#define FFA_W4W7_MBZ_REG_START (&res->a4)
+
+/* w3-w7 MBZ */
+#define FFA_W3W7_MBZ_CNT (5)
+#define FFA_W3_MBZ_REG_START (&res->a3)
+
+/* secure partitions count */
+#define SANDBOX_PARTITIONS_CNT (4)
+
+/* service 1  UUID binary data (little-endian format) */
+#define SANDBOX_SERVICE1_UUID_DATA	\
+	0xed, 0x32, 0xd5, 0x33,	\
+	0x99, 0xe6, 0x42, 0x09,	\
+	0x9c, 0xc0, 0x2d, 0x72,	\
+	0xcd, 0xd9, 0x98, 0xa7
+
+/* service 2 UUID binary data (little-endian format) */
+#define SANDBOX_SERVICE2_UUID_DATA	\
+	0xab, 0xcd, 0xd5, 0x33,	\
+	0x99, 0xe6, 0x42, 0x09,	\
+	0x9c, 0xc0, 0x2d, 0x72,	\
+	0xcd, 0xd9, 0x98, 0xa7
+
+/**
+ * struct ffa_rxtxpair_info - structure hosting the RX/TX buffers flags
+ * @rxbuf_owned:	RX buffer ownership flag (the owner is non secure world: the consumer)
+ * @rxbuf_mapped:	RX buffer mapping flag
+ * @txbuf_owned	TX buffer ownership flag
+ * @txbuf_mapped:	TX buffer mapping flag
+ * @rxtx_buf_size:	RX/TX buffers size as set by the FF-A core driver
+ *
+ * Data structure hosting the ownership/mapping flags of the RX/TX buffers
+ * When a buffer is owned/mapped its corresponding flag is set to 1 otherwise 0.
+ */
+struct ffa_rxtxpair_info {
+	u8 rxbuf_owned;
+	u8 rxbuf_mapped;
+	u8 txbuf_owned;
+	u8 txbuf_mapped;
+	u32 rxtx_buf_size;
+};
+
+/**
+ * struct sandbox_ffa_prvdata - the driver private data structure
+ *
+ * @dev:	The arm_ffa device under u-boot driver model
+ * @fwk_version:	FF-A framework version
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ * @pair_info:	The RX/TX buffers pair flags and size
+ * @conduit:	The selected conduit
+ *
+ * The driver data structure hosting all the emulated secure world data.
+ */
+struct sandbox_ffa_prvdata {
+	struct udevice *dev;
+	u32 fwk_version;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+	struct ffa_rxtxpair_info pair_info;
+	enum ffa_conduit conduit;
+};
+
+void sandbox_arm_ffa_smccc_smc(unsigned long a0, unsigned long a1,
+			       unsigned long a2, unsigned long a3, unsigned long a4,
+			       unsigned long a5, unsigned long a6, unsigned long a7,
+			       struct arm_smccc_res *res);
+
+#define SANDBOX_SMC_FFA_ABI(ffabi) static int sandbox_##ffabi(unsigned long a0, unsigned long a1, \
+				    unsigned long a2, unsigned long a3, unsigned long a4, \
+				    unsigned long a5, unsigned long a6, unsigned long a7, \
+				    struct arm_smccc_res *res)
+
+/* The core FF-A private data structure to inspect */
+extern struct ffa_prvdata ffa_priv_data;
+
+#endif
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
index 5a2151f8e4..bff565f2af 100644
--- a/include/arm_ffa.h
+++ b/include/arm_ffa.h
@@ -22,6 +22,13 @@
 #define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
 #define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
 
+/* panic only on real HW. On sandbox mode return an error code */
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+#define ffa_panic(fmt, ...) ffa_err("[FFA] " fmt "\n", ##__VA_ARGS__)
+#else
+#define ffa_panic(fmt, ...) panic("[FFA] " fmt "\n", ##__VA_ARGS__)
+#endif
+
 /*
  * The driver operations success error code
  */
@@ -184,7 +191,7 @@ const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void);
 int ffa_get_device(void);
 
 /**
- * ffa_init_device - probes the arm_ffa device
+ * ffa_init_device - probes the arm_ffa and arm_ffa devices
  */
 int ffa_init_device(void);
 #endif
diff --git a/include/sandbox_arm_ffa.h b/include/sandbox_arm_ffa.h
new file mode 100644
index 0000000000..fc681018ff
--- /dev/null
+++ b/include/sandbox_arm_ffa.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __SANDBOX_ARM_FFA_H
+#define __SANDBOX_ARM_FFA_H
+
+#include <arm_ffa.h>
+
+/**
+ * The device driver and the Uclass driver public functions
+ */
+
+/**
+ * sandbox_ffa_get_invoke_func - performs a call to the Sandbox FF-A driver dispatcher
+ */
+int sandbox_ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *func_data);
+
+/**
+ * sandbox_ffa_device_get_ops - driver operations getter
+ */
+const struct ffa_ops *sandbox_ffa_device_get_ops(void);
+
+/**
+ * sandbox_ffa_get_device - probes the sandbox_arm_ffa device
+ */
+int sandbox_ffa_get_device(void);
+
+#endif
diff --git a/include/sandbox_arm_ffa_helper.h b/include/sandbox_arm_ffa_helper.h
new file mode 100644
index 0000000000..f0fcd04536
--- /dev/null
+++ b/include/sandbox_arm_ffa_helper.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __SANDBOX_ARM_FFA_HELPER_H
+#define __SANDBOX_ARM_FFA_HELPER_H
+
+#include <arm_ffa_helper.h>
+#include <sandbox_arm_ffa.h>
+#include "../drivers/arm-ffa/sandbox_arm_ffa_prv.h"
+
+/*
+ * This header is public. Including this header provides all FF-A Sandbox data structures
+ * It also provides the helper function allowing to pass data and invoke Sandbox  FF-A functions
+ * used for testing the FF-A core driver
+ */
+
+/**
+ * sandbox_ffa_helper_query_core_state - Wrapper function for
+ *  reading the FF-A core driver data
+ */
+int sandbox_ffa_helper_query_core_state(u32 queried_func_id, struct ffa_interface_data *func_data);
+
+#endif
diff --git a/lib/arm-ffa/Makefile b/lib/arm-ffa/Makefile
index cba625fde4..04159da8eb 100644
--- a/lib/arm-ffa/Makefile
+++ b/lib/arm-ffa/Makefile
@@ -6,3 +6,4 @@
 # This file only gets included when CONFIG_ARM_FFA_TRANSPORT_HELPERS is set
 
 obj-y += arm_ffa_helper.o
+obj-$(CONFIG_SANDBOX_FFA) += sandbox_arm_ffa_helper.o
diff --git a/lib/arm-ffa/arm_ffa_helper.c b/lib/arm-ffa/arm_ffa_helper.c
index 67a3a4e9ab..32ee3b4486 100644
--- a/lib/arm-ffa/arm_ffa_helper.c
+++ b/lib/arm-ffa/arm_ffa_helper.c
@@ -105,10 +105,10 @@ int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data
 }
 
 /**
- * ffa_helper_init_device - Wrapper function for probing the arm_ffa device
+ * ffa_helper_init_device - Wrapper function for probing the arm_ffa and sandbox_arm_ffa devices
  *
- * This boot time function should be called to probe the arm_ffa device so
- * it becomes ready for use.
+ * This boot time function should be called to probe the arm_ffa and sandbox_arm_ffa devices so
+ * they become ready for use.
  * To achieve that, this function is called automatically at initcalls
  * level (after u-boot relocation).
  *
diff --git a/lib/arm-ffa/sandbox_arm_ffa_helper.c b/lib/arm-ffa/sandbox_arm_ffa_helper.c
new file mode 100644
index 0000000000..7859f30fc7
--- /dev/null
+++ b/lib/arm-ffa/sandbox_arm_ffa_helper.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <sandbox_arm_ffa_helper.h>
+
+/**
+ * sandbox_ffa_helper_query_core_state - Wrapper function for querying FF-A implementation
+ *
+ * A helper function used for querying the status of FF-A ABIs given in the input argument
+ * and the FF-A core driver.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int sandbox_ffa_helper_query_core_state(u32 queried_func_id, struct ffa_interface_data *func_data)
+{
+	return sandbox_ffa_get_invoke_func(queried_func_id, func_data);
+}
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index cffa2c69d6..12fc28fd82 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -2118,7 +2118,7 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 	struct efi_event *evt, *next_event;
 	efi_status_t ret = EFI_SUCCESS;
 
-#if defined(CONFIG_ARM_FFA_TRANSPORT)
+#if defined(CONFIG_ARM_FFA_TRANSPORT) && !defined(CONFIG_SANDBOX_FFA)
 	int ffa_ret;
 #endif
 
@@ -2182,7 +2182,7 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 		dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
 	}
 
-#if defined(CONFIG_ARM_FFA_TRANSPORT)
+#if defined(CONFIG_ARM_FFA_TRANSPORT) && !defined(CONFIG_SANDBOX_FFA)
 	/* unmap FF-A RX/TX buffers */
 	ffa_ret = ffa_helper_unmap_rxtx_buffers();
 	if (ffa_ret)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH 4/6] arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  2022-03-29 15:16 [PATCH 0/6] introduce Arm FF-A support abdellatif.elkhlifi
                   ` (2 preceding siblings ...)
  2022-03-29 15:16 ` [PATCH 3/6] arm_ffa: introduce the FF-A Sandbox driver abdellatif.elkhlifi
@ 2022-03-29 15:16 ` abdellatif.elkhlifi
  2022-03-29 15:16 ` [PATCH 5/6] arm_ffa: introduce armffa command Sandbox test abdellatif.elkhlifi
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-03-29 15:16 UTC (permalink / raw)
  To: u-boot; +Cc: nd, trini, Abdellatif El Khlifi

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

Add functional test cases for the FF-A core driver

These tests rely on the FF-A Sandbox driver which helps in
 inspecting the FF-A core driver.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
---
 MAINTAINERS      |   2 +
 test/dm/Makefile |   1 +
 test/dm/ffa.c    | 424 +++++++++++++++++++++++++++++++++++++++++++++++
 test/dm/ffa.h    |  22 +++
 4 files changed, 449 insertions(+)
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/dm/ffa.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 84524d7caf..52274b2fac 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -242,6 +242,8 @@ F:	include/arm_ffa_helper.h
 F:	include/sandbox_arm_ffa.h
 F:	include/sandbox_arm_ffa_helper.h
 F:	lib/arm-ffa/
+F:	test/dm/ffa.c
+F:	test/dm/ffa.h
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/test/dm/Makefile b/test/dm/Makefile
index d46552fbf3..48eab1b1ff 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_SANDBOX_FFA) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..82875705c6
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,424 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <dm.h>
+#include <dm/test.h>
+#include "ffa.h"
+#include <test/test.h>
+#include <test/ut.h>
+#include <sandbox_arm_ffa_helper.h>
+#include <string.h>
+
+/* Functional tests for the UCLASS_FFA */
+
+int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
+{
+	char cmd[LOG_CMD_SZ] = {0};
+
+	console_record_reset();
+
+	snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
+	run_command(cmd, 0);
+
+	ut_assert_console_end();
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_fwk_version(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (prvdata->fwk_version != SANDBOX_FWK_VERSION) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: prvdata->fwk_version = 0x%x", __func__,
+			 prvdata->fwk_version);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_endpoint_id(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (prvdata->id) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: prvdata->id = 0x%x", __func__, prvdata->id);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_dev(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->dev) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: device = 0x%p", __func__, prvdata->dev);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_prvdata_null(struct ffa_prvdata *prvdata)
+{
+	u32 idx;
+	u8 *byte = (u8 *)prvdata;
+
+	for (idx = 0 ; idx < sizeof(struct ffa_prvdata) ; idx++)
+		if (*(byte++))
+			return CMD_RET_FAILURE;
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_rxtxbuf(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->pair.rxbuf && prvdata->pair.txbuf) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = 0x%llx txbuf = 0x%llx", __func__,
+			 prvdata->pair.rxbuf,
+			 prvdata->pair.txbuf);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_features(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	u32 desc_idx;
+	char msg[LOG_MSG_SZ] = {0};
+
+	snprintf(msg,
+		 LOG_MSG_SZ,
+		 "[%s]: Error: FFA_RXTX_MAP features not found",
+		 __func__);
+
+	for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
+		if (prvdata->features[desc_idx].func_id == FFA_RXTX_MAP) {
+			if (prvdata->features[desc_idx].field1 != RXTX_4K &&
+			    prvdata->features[desc_idx].field1 != RXTX_16K &&
+			    prvdata->features[desc_idx].field1 != RXTX_64K) {
+				snprintf(msg,
+					 LOG_MSG_SZ,
+					 "[%s]: Error: FFA_RXTX_MAP features = 0x%x",
+					 __func__,
+					 prvdata->features[desc_idx].field1);
+					break;
+			}
+			return CMD_RET_SUCCESS;
+		}
+
+	dm_test_ffa_log(uts, msg);
+	return CMD_RET_FAILURE;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+	{
+		if (rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	case FFA_RXTX_UNMAP:
+	{
+		if (!rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	default:
+		return CMD_RET_FAILURE;
+	}
+
+	snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__,
+		 (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP"));
+	dm_test_ffa_log(uts, msg);
+
+	return CMD_RET_FAILURE;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	if (rxbuf_owned) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_interface_data func_data = {0};
+	struct ffa_send_direct_data msg = {0};
+	u32 pattern = 0xaabbccdd;
+	u8 cnt;
+
+	/*
+	 * telling the driver which partition to use
+	 */
+	func_data.data0_size = sizeof(part_id);
+	func_data.data0 = &part_id;
+
+	/*
+	 * filling the message data
+	 */
+	msg.a3 = pattern;
+	msg.a4 = pattern;
+	msg.a5 = pattern;
+	msg.a6 = pattern;
+	msg.a7 = pattern;
+	func_data.data1_size = sizeof(msg);
+	func_data.data1 = &msg;
+
+	ut_assertok(ffa_helper_msg_send_direct_req(&func_data));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u32); cnt++)
+		ut_assertok(((u32 *)&msg)[cnt] != 0xffffffff);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int test_partitions_and_comms(union ffa_partition_uuid *service_uuid,
+				     struct sandbox_ffa_prvdata *sdx_prvdata,
+				     struct unit_test_state *uts)
+{
+	struct ffa_interface_data func_data = {0};
+	u32 count = 0;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx, exp_info_idx;
+	int ret;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	func_data.data0_size = sizeof(*service_uuid);
+	func_data.data0 = service_uuid;
+	func_data.data1_size = sizeof(count);
+	func_data.data1 = &count;
+
+	ut_assertok(ffa_helper_get_partitions_info(&func_data));
+
+	/* make sure partitions are detected */
+	ut_assertok(!count);
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	ut_assertok(!parts_info);
+
+	func_data.data1_size = count * sizeof(struct ffa_partition_info);
+	func_data.data1 = parts_info;
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+	ret = ffa_helper_get_partitions_info(&func_data);
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		free(parts_info);
+		ut_assertok(ret != FFA_ERR_STAT_SUCCESS);
+	}
+
+	/*
+	 * SPs found , verify the partitions information
+	 */
+
+	ret = CMD_RET_FAILURE;
+
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		for (exp_info_idx = 0;
+		     exp_info_idx < sdx_prvdata->partitions.count;
+		     exp_info_idx++) {
+			if (parts_info[info_idx].id ==
+			   sdx_prvdata->partitions.descs[exp_info_idx].info.id) {
+				ret = memcmp(&parts_info[info_idx],
+					     &sdx_prvdata->partitions.descs[exp_info_idx]
+					     .info,
+					     sizeof(struct ffa_partition_info));
+				if (ret)
+					free(parts_info);
+				ut_assertok(ret != 0);
+				/* send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
+			}
+			ret = CMD_RET_SUCCESS;
+		}
+	}
+
+	free(parts_info);
+
+	/* Verify  expected partitions found in the emulated secure world*/
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+	struct ffa_interface_data func_data = {0};
+	u8 rxbuf_flag = 0;
+	union ffa_partition_uuid svc1_uuid = { .bytes = {SANDBOX_SERVICE1_UUID_DATA}};
+	union ffa_partition_uuid svc2_uuid = { .bytes = {SANDBOX_SERVICE2_UUID_DATA}};
+	int ret;
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+
+	ut_assertok(sandbox_ffa_helper_query_core_state(FFA_VERSION, &func_data));
+
+	/* make sure the core private data is cleared before use */
+	ut_assertok(check_prvdata_null(prvdata));
+
+	/*  test probing FF-A devices */
+	ut_assertok(ffa_helper_init_device());
+	ut_assertok(check_dev(prvdata, uts));
+
+	/* test FFA_VERSION */
+	ut_assertok(check_fwk_version(prvdata, uts));
+
+	/* test FFA_ID_GET */
+	ut_assertok(check_endpoint_id(prvdata, uts));
+
+	/* test FFA_FEATURES */
+	ut_assertok(check_features(prvdata, uts));
+
+	/*  test core RX/TX buffers */
+	ut_assertok(check_rxtxbuf(prvdata, uts));
+
+	/* test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	ut_assertok(sandbox_ffa_helper_query_core_state(FFA_RXTX_MAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(&svc1_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_helper_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(&svc2_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_helper_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* test FFA_RXTX_UNMAP */
+	ut_assertok(ffa_helper_unmap_rxtx_buffers());
+
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_helper_query_core_state(FFA_RXTX_UNMAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+
+	struct ffa_interface_data func_data = {0};
+	union ffa_partition_uuid valid_svc_uuid = { .bytes = {SANDBOX_SERVICE1_UUID_DATA}};
+	union ffa_partition_uuid unvalid_svc_uuid = { .bytes = {SANDBOX_SERVICE3_UUID_DATA}};
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	u32 count = 0;
+	u16 part_id = 0;
+
+	/* get partitions info before probing the core driver */
+	func_data.data0_size = sizeof(union ffa_partition_uuid);
+	func_data.data0 = &unvalid_svc_uuid;
+	func_data.data1_size = sizeof(count);
+	func_data.data1 = &count;
+
+	ret = ffa_helper_get_partitions_info(&func_data);
+	ut_assertok(ret != -ENODEV);
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+	ut_assertok(sandbox_ffa_helper_query_core_state(FFA_VERSION, &func_data));
+
+	/*  probing FF-A devices */
+	ut_assertok(ffa_helper_init_device());
+	ut_assertok(check_dev(prvdata, uts));
+
+	/* query partition info using  invalid arguments  */
+	ret = ffa_helper_get_partitions_info(&func_data);
+	ut_assertok(ret != -EINVAL);
+
+	/* query partition info using an invalid UUID  */
+	func_data.data0_size = sizeof(union ffa_partition_uuid);
+	func_data.data0 = &unvalid_svc_uuid;
+	func_data.data1_size = sizeof(count);
+	func_data.data1 = &count;
+
+	ret = ffa_helper_get_partitions_info(&func_data);
+	ut_assertok(ret != -EPERM);
+
+	/* query partition info using a valid UUID  */
+	func_data.data0 = &valid_svc_uuid;
+	count = 0;
+	ret = ffa_helper_get_partitions_info(&func_data);
+	/* make sure partitions are detected */
+	ut_assertok(ret != FFA_ERR_STAT_SUCCESS);
+	ut_assertok(!count);
+
+	/* send data to an invalid partition */
+	func_data.data0_size = sizeof(part_id);
+	func_data.data0 = &part_id;
+	func_data.data1_size = sizeof(msg);
+	func_data.data1 = &msg;
+
+	ret = ffa_helper_msg_send_direct_req(&func_data);
+	ut_assertok(ret != -EPERM);
+
+	/* send data to a valid partition */
+	part_id = ffa_priv_data.partitions.descs[0].info.id;
+	ret = ffa_helper_msg_send_direct_req(&func_data);
+	ut_assertok(ret != FFA_ERR_STAT_SUCCESS);
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
diff --git a/test/dm/ffa.h b/test/dm/ffa.h
new file mode 100644
index 0000000000..11c7980fcf
--- /dev/null
+++ b/test/dm/ffa.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __TEST_DM_FFA_H
+#define __TEST_DM_FFA_H
+
+#define SANDBOX_FWK_VERSION (0x10000)
+
+#define LOG_MSG_SZ (100)
+#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
+
+/* service 3  UUID binary data (little-endian format) */
+#define SANDBOX_SERVICE3_UUID_DATA	\
+	0xfd, 0x42, 0xd5, 0x33,	\
+	0x19, 0xa6, 0x42, 0x09,	\
+	0x9c, 0xc1, 0x2d, 0x72,	\
+	0xcd, 0xd9, 0x98, 0x89
+
+#endif /*__TEST_DM_FFA_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH 5/6] arm_ffa: introduce armffa command Sandbox test
  2022-03-29 15:16 [PATCH 0/6] introduce Arm FF-A support abdellatif.elkhlifi
                   ` (3 preceding siblings ...)
  2022-03-29 15:16 ` [PATCH 4/6] arm_ffa: introduce Sandbox test cases for UCLASS_FFA abdellatif.elkhlifi
@ 2022-03-29 15:16 ` abdellatif.elkhlifi
  2022-03-29 15:16 ` [PATCH 6/6] arm_ffa: introduce FF-A MM communication abdellatif.elkhlifi
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-03-29 15:16 UTC (permalink / raw)
  To: u-boot; +Cc: nd, trini, Abdellatif El Khlifi

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

Add Sandbox test for the armffa command

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
---
 MAINTAINERS       |  2 ++
 test/cmd/Makefile |  1 +
 test/cmd/armffa.c | 33 +++++++++++++++++++++++++++++++++
 test/cmd/armffa.h | 13 +++++++++++++
 4 files changed, 49 insertions(+)
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/cmd/armffa.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 52274b2fac..9828095837 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -242,6 +242,8 @@ F:	include/arm_ffa_helper.h
 F:	include/sandbox_arm_ffa.h
 F:	include/sandbox_arm_ffa_helper.h
 F:	lib/arm-ffa/
+F:	test/cmd/armffa.c
+F:	test/cmd/armffa.h
 F:	test/dm/ffa.c
 F:	test/dm/ffa.h
 
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index a59adb1e6d..d9dc0809d6 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
 obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PWM) += pwm.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_SANDBOX_FFA) += armffa.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..d35032047b
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include "armffa.h"
+#include <arm_ffa_helper.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	ut_assertok(ffa_helper_init_device());
+
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SE_PROXY_PARTITION_UUID, 0));
+
+	/* armffa ping <ID> */
+	ut_assertok(run_command("armffa ping " SE_PROXY_PARTITION_ID, 0));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
diff --git a/test/cmd/armffa.h b/test/cmd/armffa.h
new file mode 100644
index 0000000000..630dc75e25
--- /dev/null
+++ b/test/cmd/armffa.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __TEST_CMD_FFA_H
+#define __TEST_CMD_FFA_H
+
+#define SE_PROXY_PARTITION_ID "0x1245"
+#define SE_PROXY_PARTITION_UUID "33d532ed-e699-0942-c09c-a798d9cd722d"
+
+#endif /*__TEST_CMD_FFA_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH 6/6] arm_ffa: introduce FF-A MM communication
  2022-03-29 15:16 [PATCH 0/6] introduce Arm FF-A support abdellatif.elkhlifi
                   ` (4 preceding siblings ...)
  2022-03-29 15:16 ` [PATCH 5/6] arm_ffa: introduce armffa command Sandbox test abdellatif.elkhlifi
@ 2022-03-29 15:16 ` abdellatif.elkhlifi
  2022-04-14 19:54   ` Ilias Apalodimas
  2022-04-06 15:51 ` [PATCH 0/6] introduce Arm FF-A support Abdellatif El Khlifi
  2022-04-06 19:47 ` Tom Rini
  7 siblings, 1 reply; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-03-29 15:16 UTC (permalink / raw)
  To: u-boot; +Cc: nd, trini, Abdellatif El Khlifi, Gowtham Suresh Kumar

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

Add MM communication support using FF-A transport

FF-A MM communication allows exchanging data with StandAlonneMM
or smm-gateway secure partitions which run in OP-TEE.

An MM shared buffer and a door bell event are used to exchange
this data.

The data is used by EFI services such as GetVariable()/SetVariable()
 and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
 MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
 buffer with the response data.

The response data is copied back to the communication buffer and
 consumed by the EFI subsystem.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
Cc: Tom Rini <trini@konsulko.com>
---
 arch/arm/cpu/armv8/cache.S        |  16 ++
 arch/arm/cpu/armv8/cache_v8.c     |   3 +-
 include/mm_communication.h        |   4 +-
 lib/efi_loader/Kconfig            |  14 +-
 lib/efi_loader/efi_variable_tee.c | 294 +++++++++++++++++++++++++++++-
 5 files changed, 321 insertions(+), 10 deletions(-)

diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S
index d1cee23437..bdbe89e0c5 100644
--- a/arch/arm/cpu/armv8/cache.S
+++ b/arch/arm/cpu/armv8/cache.S
@@ -21,7 +21,11 @@
  * x1: 0 clean & invalidate, 1 invalidate only
  * x2~x9: clobbered
  */
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_dcache_level, "ax"
+#endif
 ENTRY(__asm_dcache_level)
 	lsl	x12, x0, #1
 	msr	csselr_el1, x12		/* select cache level */
@@ -65,7 +69,11 @@ ENDPROC(__asm_dcache_level)
  *
  * flush or invalidate all data cache by SET/WAY.
  */
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_dcache_all, "ax"
+#endif
 ENTRY(__asm_dcache_all)
 	mov	x1, x0
 	dsb	sy
@@ -109,7 +117,11 @@ ENTRY(__asm_flush_dcache_all)
 ENDPROC(__asm_flush_dcache_all)
 .popsection
 
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_invalidate_dcache_all, "ax"
+#endif
 ENTRY(__asm_invalidate_dcache_all)
 	mov	x0, #0x1
 	b	__asm_dcache_all
@@ -182,7 +194,11 @@ ENTRY(__asm_invalidate_icache_all)
 ENDPROC(__asm_invalidate_icache_all)
 .popsection
 
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_invalidate_l3_dcache, "ax"
+#endif
 WEAK(__asm_invalidate_l3_dcache)
 	mov	x0, #0			/* return status as success */
 	ret
diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index 3de18c7675..187a4497a7 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -9,6 +9,7 @@
 
 #include <common.h>
 #include <cpu_func.h>
+#include <efi_loader.h>
 #include <hang.h>
 #include <log.h>
 #include <asm/cache.h>
@@ -425,7 +426,7 @@ __weak void mmu_setup(void)
 /*
  * Performs a invalidation of the entire data cache at all levels
  */
-void invalidate_dcache_all(void)
+void __efi_runtime invalidate_dcache_all(void)
 {
 	__asm_invalidate_dcache_all();
 	__asm_invalidate_l3_dcache();
diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..bb99190956 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -123,7 +123,7 @@ struct __packed efi_mm_communicate_header {
  *
  * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_HEADER.
  */
-struct smm_variable_communicate_header {
+struct __packed smm_variable_communicate_header {
 	efi_uintn_t  function;
 	efi_status_t ret_status;
 	u8           data[];
@@ -145,7 +145,7 @@ struct smm_variable_communicate_header {
  * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
  *
  */
-struct smm_variable_access {
+struct __packed smm_variable_access {
 	efi_guid_t  guid;
 	efi_uintn_t data_size;
 	efi_uintn_t name_size;
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 28657f50c9..0d69133595 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	depends on OPTEE || ARM_FFA_TRANSPORT
 	help
+	  The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver, StandAlonneMM and smm-gateway are supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running under Optee in the trusted world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
 endchoice
 
 config EFI_VARIABLES_PRESEED
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..3d01985662 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -15,6 +15,53 @@
 #include <malloc.h>
 #include <mm_communication.h>
 
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+#include <arm_ffa_helper.h>
+#include <cpu_func.h>
+#include <mapmem.h>
+
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+
+#include <linux/sizes.h>
+#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
+
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+
+/*
+ * shared buffer physical address used for communication between
+ * u-boot and the MM SP
+ */
+#define FFA_SHARED_MM_BUFFER_ADDR	(0x023F8000)
+
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+
+#define ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64 (0xC4000061)
+#define ARM_SVC_ID_SP_EVENT_COMPLETE ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64
+
+#ifndef MM_SP_UUID_DATA
+
+/* MM SP UUID binary data (little-endian format) */
+#define MM_SP_UUID_DATA	\
+	0xed, 0x32, 0xd5, 0x33,	\
+	0x99, 0xe6, 0x42, 0x09,	\
+	0x9c, 0xc0, 0x2d, 0x72,	\
+	0xcd, 0xd9, 0x98, 0xa7
+
+#endif
+
+/* MM_SP_UUID_DATA defined by the platform */
+union ffa_partition_uuid mm_sp_svc_uuid = {.bytes = {MM_SP_UUID_DATA}};
+
+static __efi_runtime_data u16 mm_sp_id;
+
+#endif
+
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -24,6 +71,7 @@ struct mm_connection {
 	u32 session;
 };
 
+#if (IS_ENABLED(CONFIG_OPTEE))
 /**
  * get_connection() - Retrieve OP-TEE session for a specific UUID.
  *
@@ -143,16 +191,238 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 
 	return ret;
 }
+#endif
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+/**
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notifies the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int __efi_runtime ffa_notify_mm_sp(void)
+{
+	struct ffa_interface_data func_data = {0};
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	u32 sp_event_complete;
+	int sp_event_ret;
+
+	func_data.data0_size = sizeof(mm_sp_id);
+	func_data.data0 = &mm_sp_id;
+
+	msg.a3 = FFA_SHARED_MM_BUFFER_ADDR;
+	msg.a4 = FFA_SHARED_MM_BUFFER_SIZE;
+	func_data.data1_size = sizeof(msg);
+	func_data.data1 = &msg;
+
+	ret = ffa_helper_msg_send_direct_req(&func_data);
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	sp_event_complete = msg.a3;
+	sp_event_ret = (int)msg.a4;
+
+	if (sp_event_complete == ARM_SVC_ID_SP_EVENT_COMPLETE && sp_event_ret == MM_SUCCESS)
+		return 0;
+
+	/*
+	 * Failure to notify the MM SP
+	 */
+
+	return -EACCES;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	struct ffa_interface_data func_data = {0};
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	func_data.data0_size = sizeof(mm_sp_svc_uuid);
+	func_data.data0 = &mm_sp_svc_uuid;
+	func_data.data1_size = sizeof(count);
+	func_data.data1 = &count;
+
+	ret = ffa_helper_get_partitions_info(&func_data);
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
+		return ret;
+	}
+
+	if (!count) {
+		log_info("EFI: No MM partition found\n");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
+
+	func_data.data1_size = count *
+		sizeof(struct ffa_partition_info);
+	func_data.data1 = parts_info;
+
+	/*
+	 * ask the driver to fill the
+	 * buffer with the SPs info
+	 */
+	ret = ffa_helper_get_partitions_info(&func_data);
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * MM SPs found , use the first one
+	 */
+
+	mm_sp_id = parts_info[0].id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	free(parts_info);
+
+	return 0;
+}
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t __efi_runtime ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()  != FFA_ERR_STAT_SUCCESS) {
+		log_err("EFI: Failure to discover MM partition ID at boot time\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	efi_memcpy_runtime(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world has cache disabled for device region which we use for shared buffer.
+	 * So, the secure world reads the data from DRAM. Let's flush the cache so the DRAM is
+	 * updated with the latest data.
+	 */
+	#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+	#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+	if (ffa_ret)
+		unmap_sysmem(virt_shared_buf);
+
+	switch (ffa_ret) {
+	case 0:
+	{
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_memcpy_runtime(comm_buf, virt_shared_buf, comm_buf_size);
+			unmap_sysmem(virt_shared_buf);
+			return EFI_BUFFER_TOO_SMALL;
+		}
+
+		efi_memcpy_runtime(comm_buf, virt_shared_buf, rx_data_size);
+		unmap_sysmem(virt_shared_buf);
+
+		return EFI_SUCCESS;
+	}
+	case -EINVAL:
+		return EFI_DEVICE_ERROR;
+	case -EPERM:
+		return EFI_INVALID_PARAMETER;
+	case -EACCES:
+		return EFI_ACCESS_DENIED;
+	case -EBUSY:
+		return EFI_OUT_OF_RESOURCES;
+	default:
+		return EFI_ACCESS_DENIED;
+	}
+}
+#endif
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, StandAlonneMM and smm-gateway are supported.
+ *
  * Return:		status code
  */
-static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
+static efi_status_t __efi_runtime mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 {
 	efi_status_t ret;
 	struct efi_mm_communicate_header *mm_hdr;
@@ -162,9 +432,16 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
+	#if (IS_ENABLED(CONFIG_OPTEE))
 	ret = optee_mm_communicate(comm_buf, dsize);
+	#elif (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+	ret = ffa_mm_communicate(comm_buf, dsize);
+	#endif
 	if (ret != EFI_SUCCESS) {
-		log_err("%s failed!\n", __func__);
+		/* No need for showing a log here. mm_communicate failure happens
+		 * when getVariable() is called with data size set to 0.
+		 * This is not expected so no log shown.
+		 */
 		return ret;
 	}
 
@@ -258,6 +535,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
 		goto out;
 	}
 	*size = var_payload->size;
+
+	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
+			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
+				MM_VARIABLE_COMMUNICATE_SIZE;
+	#endif
+
 	/*
 	 * There seems to be a bug in EDK2 miscalculating the boundaries and
 	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
@@ -697,7 +981,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-03-29 15:16 [PATCH 0/6] introduce Arm FF-A support abdellatif.elkhlifi
                   ` (5 preceding siblings ...)
  2022-03-29 15:16 ` [PATCH 6/6] arm_ffa: introduce FF-A MM communication abdellatif.elkhlifi
@ 2022-04-06 15:51 ` Abdellatif El Khlifi
  2022-04-06 19:47 ` Tom Rini
  7 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-04-06 15:51 UTC (permalink / raw)
  To: u-boot, trini; +Cc: Vishnu.Banavath, Xueliang.Zhong

Hello guys, gentle ping, any thoughts about these changes ?

On Tue, Mar 29, 2022 at 04:16:53PM +0100, abdellatif.elkhlifi@arm.com wrote:
> From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> 
> This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> 
> FF-A support is generic by design and can be used by any Arm platform.
> 
> The features added are as follows:
>     
> 1/ FF-A device driver
> 2/ armffa command
> 3/ FF-A Sandbox driver
> 4/ FF-A Sandbox test cases
> 5/ FF-A MM communication
> 
> 
> The suggested design sees FF-A as a data bus allowing data exchange with the firmware
> running under TrustZone HW (such as Optee). The same approach was followed in the
> FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> 
> u-boot boards using FF-A can provide a device tree node in a <board>-u-boot.dtsi file.
> Since the node can not be hosted in Linux device tree, we suggest using u-boot device tree.
> 
> As a use case, we will send  a commit enabling FF-A for the Corstone-1000 platform and providing
> the FF-A node in u-boot.dtsi files.
> 
> Corstone-1000: https://lore.kernel.org/u-boot/20220322104118.573537-1-rui.silva@linaro.org/
> 
> Cc: Tom Rini <trini@konsulko.com>
> 
> Abdellatif El Khlifi (6):
>   arm_ffa: introduce Arm FF-A low-level driver
>   arm_ffa: introduce armffa command
>   arm_ffa: introduce the FF-A Sandbox driver
>   arm_ffa: introduce Sandbox test cases for UCLASS_FFA
>   arm_ffa: introduce armffa command Sandbox test
>   arm_ffa: introduce FF-A MM communication
> 
>  MAINTAINERS                           |   15 +
>  arch/arm/cpu/armv8/cache.S            |   16 +
>  arch/arm/cpu/armv8/cache_v8.c         |    3 +-
>  arch/arm/cpu/armv8/smccc-call.S       |   27 +
>  arch/arm/lib/asm-offsets.c            |    6 +
>  arch/sandbox/dts/sandbox.dtsi         |   10 +
>  arch/sandbox/dts/test.dts             |   10 +
>  cmd/Kconfig                           |   10 +
>  cmd/Makefile                          |    2 +
>  cmd/armffa.c                          |  266 +++++
>  common/board_r.c                      |    7 +
>  configs/sandbox64_defconfig           |    2 +
>  configs/sandbox_defconfig             |    2 +
>  doc/arch/sandbox.rst                  |    1 +
>  drivers/Kconfig                       |    2 +
>  drivers/Makefile                      |    1 +
>  drivers/arm-ffa/Kconfig               |   32 +
>  drivers/arm-ffa/Makefile              |    7 +
>  drivers/arm-ffa/arm-ffa-uclass.c      |  102 ++
>  drivers/arm-ffa/arm_ffa_prv.h         |  200 ++++
>  drivers/arm-ffa/core.c                | 1463 +++++++++++++++++++++++++
>  drivers/arm-ffa/sandbox.c             |  735 +++++++++++++
>  drivers/arm-ffa/sandbox_arm_ffa_prv.h |  128 +++
>  include/arm_ffa.h                     |  197 ++++
>  include/arm_ffa_helper.h              |   45 +
>  include/dm/uclass-id.h                |    1 +
>  include/linux/arm-smccc.h             |   28 +-
>  include/mm_communication.h            |    4 +-
>  include/sandbox_arm_ffa.h             |   31 +
>  include/sandbox_arm_ffa_helper.h      |   26 +
>  lib/Kconfig                           |    1 +
>  lib/Makefile                          |    1 +
>  lib/arm-ffa/Kconfig                   |    6 +
>  lib/arm-ffa/Makefile                  |    9 +
>  lib/arm-ffa/arm_ffa_helper.c          |  188 ++++
>  lib/arm-ffa/sandbox_arm_ffa_helper.c  |   23 +
>  lib/efi_loader/Kconfig                |   14 +-
>  lib/efi_loader/efi_boottime.c         |   17 +
>  lib/efi_loader/efi_variable_tee.c     |  294 ++++-
>  test/cmd/Makefile                     |    1 +
>  test/cmd/armffa.c                     |   33 +
>  test/cmd/armffa.h                     |   13 +
>  test/dm/Makefile                      |    1 +
>  test/dm/ffa.c                         |  424 +++++++
>  test/dm/ffa.h                         |   22 +
>  45 files changed, 4415 insertions(+), 11 deletions(-)
>  create mode 100644 cmd/armffa.c
>  create mode 100644 drivers/arm-ffa/Kconfig
>  create mode 100644 drivers/arm-ffa/Makefile
>  create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
>  create mode 100644 drivers/arm-ffa/core.c
>  create mode 100644 drivers/arm-ffa/sandbox.c
>  create mode 100644 drivers/arm-ffa/sandbox_arm_ffa_prv.h
>  create mode 100644 include/arm_ffa.h
>  create mode 100644 include/arm_ffa_helper.h
>  create mode 100644 include/sandbox_arm_ffa.h
>  create mode 100644 include/sandbox_arm_ffa_helper.h
>  create mode 100644 lib/arm-ffa/Kconfig
>  create mode 100644 lib/arm-ffa/Makefile
>  create mode 100644 lib/arm-ffa/arm_ffa_helper.c
>  create mode 100644 lib/arm-ffa/sandbox_arm_ffa_helper.c
>  create mode 100644 test/cmd/armffa.c
>  create mode 100644 test/cmd/armffa.h
>  create mode 100644 test/dm/ffa.c
>  create mode 100644 test/dm/ffa.h
> 
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-03-29 15:16 [PATCH 0/6] introduce Arm FF-A support abdellatif.elkhlifi
                   ` (6 preceding siblings ...)
  2022-04-06 15:51 ` [PATCH 0/6] introduce Arm FF-A support Abdellatif El Khlifi
@ 2022-04-06 19:47 ` Tom Rini
  2022-04-07 12:54   ` Abdellatif El Khlifi
  7 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2022-04-06 19:47 UTC (permalink / raw)
  To: abdellatif.elkhlifi; +Cc: u-boot, nd

[-- Attachment #1: Type: text/plain, Size: 1169 bytes --]

On Tue, Mar 29, 2022 at 04:16:53PM +0100, abdellatif.elkhlifi@arm.com wrote:
> From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> 
> This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> 
> FF-A support is generic by design and can be used by any Arm platform.
> 
> The features added are as follows:
>     
> 1/ FF-A device driver
> 2/ armffa command
> 3/ FF-A Sandbox driver
> 4/ FF-A Sandbox test cases
> 5/ FF-A MM communication
> 
> 
> The suggested design sees FF-A as a data bus allowing data exchange with the firmware
> running under TrustZone HW (such as Optee). The same approach was followed in the
> FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> 
> u-boot boards using FF-A can provide a device tree node in a <board>-u-boot.dtsi file.
> Since the node can not be hosted in Linux device tree, we suggest using u-boot device tree.

Why can't the node be in the upstream tree?  It should be, so that it
can be shared between all users.  Especially since there's in-Linux
users?

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-04-06 19:47 ` Tom Rini
@ 2022-04-07 12:54   ` Abdellatif El Khlifi
  2022-04-07 12:58     ` Tom Rini
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-04-07 12:54 UTC (permalink / raw)
  To: Tom Rini; +Cc: u-boot, nd, vishnu.banavath, xueliang.zhong, abdellatif.elkhlifi

On Wed, Apr 06, 2022 at 03:47:11PM -0400, Tom Rini wrote:
> On Tue, Mar 29, 2022 at 04:16:53PM +0100, abdellatif.elkhlifi@arm.com wrote:
> > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > 
> > This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> > 
> > FF-A support is generic by design and can be used by any Arm platform.
> > 
> > The features added are as follows:
> >     
> > 1/ FF-A device driver
> > 2/ armffa command
> > 3/ FF-A Sandbox driver
> > 4/ FF-A Sandbox test cases
> > 5/ FF-A MM communication
> > 
> > 
> > The suggested design sees FF-A as a data bus allowing data exchange with the firmware
> > running under TrustZone HW (such as Optee). The same approach was followed in the
> > FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> > 
> > u-boot boards using FF-A can provide a device tree node in a <board>-u-boot.dtsi file.
> > Since the node can not be hosted in Linux device tree, we suggest using u-boot device tree.
> 
> Why can't the node be in the upstream tree?  It should be, so that it
> can be shared between all users.  Especially since there's in-Linux
> users?
> 
> -- 
> Tom

Linux already has an FF-A bus driver and doesn't use a device tree node for FF-A.

The Linux driver registers FF-A as a bus:

int arm_ffa_bus_init(void)
{
	return bus_register(&ffa_bus_type);
}

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211

So, there is no user for the node in Linux. That's why we suggest hosting the node in the u-boot device tree (a u-boot.dtsi file)


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-04-07 12:54   ` Abdellatif El Khlifi
@ 2022-04-07 12:58     ` Tom Rini
  2022-04-12 11:43       ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2022-04-07 12:58 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: u-boot, nd, vishnu.banavath, xueliang.zhong

[-- Attachment #1: Type: text/plain, Size: 2000 bytes --]

On Thu, Apr 07, 2022 at 01:54:24PM +0100, Abdellatif El Khlifi wrote:
> On Wed, Apr 06, 2022 at 03:47:11PM -0400, Tom Rini wrote:
> > On Tue, Mar 29, 2022 at 04:16:53PM +0100, abdellatif.elkhlifi@arm.com wrote:
> > > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > 
> > > This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> > > 
> > > FF-A support is generic by design and can be used by any Arm platform.
> > > 
> > > The features added are as follows:
> > >     
> > > 1/ FF-A device driver
> > > 2/ armffa command
> > > 3/ FF-A Sandbox driver
> > > 4/ FF-A Sandbox test cases
> > > 5/ FF-A MM communication
> > > 
> > > 
> > > The suggested design sees FF-A as a data bus allowing data exchange with the firmware
> > > running under TrustZone HW (such as Optee). The same approach was followed in the
> > > FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> > > 
> > > u-boot boards using FF-A can provide a device tree node in a <board>-u-boot.dtsi file.
> > > Since the node can not be hosted in Linux device tree, we suggest using u-boot device tree.
> > 
> > Why can't the node be in the upstream tree?  It should be, so that it
> > can be shared between all users.  Especially since there's in-Linux
> > users?
> > 
> > -- 
> > Tom
> 
> Linux already has an FF-A bus driver and doesn't use a device tree node for FF-A.
> 
> The Linux driver registers FF-A as a bus:
> 
> int arm_ffa_bus_init(void)
> {
> 	return bus_register(&ffa_bus_type);
> }
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211
> 
> So, there is no user for the node in Linux. That's why we suggest hosting the node in the u-boot device tree (a u-boot.dtsi file)

OK, but you can still push it upstream as it's not required to have an
in tree user.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-04-07 12:58     ` Tom Rini
@ 2022-04-12 11:43       ` Abdellatif El Khlifi
  2022-04-12 12:01         ` Tom Rini
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-04-12 11:43 UTC (permalink / raw)
  To: Tom Rini
  Cc: u-boot, vishnu.banavath, xueliang.zhong, abdellatif.elkhlifi, nd,
	rui.silva, rob.herring

On Thu, Apr 07, 2022 at 08:58:11AM -0400, Tom Rini wrote:
> On Thu, Apr 07, 2022 at 01:54:24PM +0100, Abdellatif El Khlifi wrote:
> > On Wed, Apr 06, 2022 at 03:47:11PM -0400, Tom Rini wrote:
> > > On Tue, Mar 29, 2022 at 04:16:53PM +0100, abdellatif.elkhlifi@arm.com wrote:
> > > > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > 
> > > > This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> > > > 
> > > > FF-A support is generic by design and can be used by any Arm platform.
> > > > 
> > > > The features added are as follows:
> > > >     
> > > > 1/ FF-A device driver
> > > > 2/ armffa command
> > > > 3/ FF-A Sandbox driver
> > > > 4/ FF-A Sandbox test cases
> > > > 5/ FF-A MM communication
> > > > 
> > > > 
> > > > The suggested design sees FF-A as a data bus allowing data exchange with the firmware
> > > > running under TrustZone HW (such as Optee). The same approach was followed in the
> > > > FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> > > > 
> > > > u-boot boards using FF-A can provide a device tree node in a <board>-u-boot.dtsi file.
> > > > Since the node can not be hosted in Linux device tree, we suggest using u-boot device tree.
> > > 
> > > Why can't the node be in the upstream tree?  It should be, so that it
> > > can be shared between all users.  Especially since there's in-Linux
> > > users?
> > > 
> > > -- 
> > > Tom
> > 
> > Linux already has an FF-A bus driver and doesn't use a device tree node for FF-A.
> > 
> > The Linux driver registers FF-A as a bus:
> > 
> > int arm_ffa_bus_init(void)
> > {
> > 	return bus_register(&ffa_bus_type);
> > }
> > 
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211
> > 
> > So, there is no user for the node in Linux. That's why we suggest hosting the node in the u-boot device tree (a u-boot.dtsi file)
> 
> OK, but you can still push it upstream as it's not required to have an
> in tree user.
> 
> -- 
> Tom

During the review of Corstone-1000 patchset, Rui Silva had a discussion with the Linux device tree maintainer
(Rob Herring). Rob is not in favour of an FFA node in the kernel device tree. This is why we are including the FFA node
in u-boot device tree (u-boot.dtsi files).

--
Abdellatif


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-04-12 11:43       ` Abdellatif El Khlifi
@ 2022-04-12 12:01         ` Tom Rini
  2022-04-12 13:28           ` Rob Herring
  0 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2022-04-12 12:01 UTC (permalink / raw)
  To: Abdellatif El Khlifi, rob.herring
  Cc: u-boot, vishnu.banavath, xueliang.zhong, nd, rui.silva

[-- Attachment #1: Type: text/plain, Size: 2715 bytes --]

On Tue, Apr 12, 2022 at 12:43:15PM +0100, Abdellatif El Khlifi wrote:
> On Thu, Apr 07, 2022 at 08:58:11AM -0400, Tom Rini wrote:
> > On Thu, Apr 07, 2022 at 01:54:24PM +0100, Abdellatif El Khlifi wrote:
> > > On Wed, Apr 06, 2022 at 03:47:11PM -0400, Tom Rini wrote:
> > > > On Tue, Mar 29, 2022 at 04:16:53PM +0100, abdellatif.elkhlifi@arm.com wrote:
> > > > > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > > 
> > > > > This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> > > > > 
> > > > > FF-A support is generic by design and can be used by any Arm platform.
> > > > > 
> > > > > The features added are as follows:
> > > > >     
> > > > > 1/ FF-A device driver
> > > > > 2/ armffa command
> > > > > 3/ FF-A Sandbox driver
> > > > > 4/ FF-A Sandbox test cases
> > > > > 5/ FF-A MM communication
> > > > > 
> > > > > 
> > > > > The suggested design sees FF-A as a data bus allowing data exchange with the firmware
> > > > > running under TrustZone HW (such as Optee). The same approach was followed in the
> > > > > FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> > > > > 
> > > > > u-boot boards using FF-A can provide a device tree node in a <board>-u-boot.dtsi file.
> > > > > Since the node can not be hosted in Linux device tree, we suggest using u-boot device tree.
> > > > 
> > > > Why can't the node be in the upstream tree?  It should be, so that it
> > > > can be shared between all users.  Especially since there's in-Linux
> > > > users?
> > > > 
> > > > -- 
> > > > Tom
> > > 
> > > Linux already has an FF-A bus driver and doesn't use a device tree node for FF-A.
> > > 
> > > The Linux driver registers FF-A as a bus:
> > > 
> > > int arm_ffa_bus_init(void)
> > > {
> > > 	return bus_register(&ffa_bus_type);
> > > }
> > > 
> > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211
> > > 
> > > So, there is no user for the node in Linux. That's why we suggest hosting the node in the u-boot device tree (a u-boot.dtsi file)
> > 
> > OK, but you can still push it upstream as it's not required to have an
> > in tree user.
> 
> During the review of Corstone-1000 patchset, Rui Silva had a discussion with the Linux device tree maintainer
> (Rob Herring). Rob is not in favour of an FFA node in the kernel device tree. This is why we are including the FFA node
> in u-boot device tree (u-boot.dtsi files).

I'm a bit confused now, can you please link to the kernel thread?  Or
Rob, can you chime in here please?

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-04-12 12:01         ` Tom Rini
@ 2022-04-12 13:28           ` Rob Herring
  2022-04-13 14:20             ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Rob Herring @ 2022-04-12 13:28 UTC (permalink / raw)
  To: Tom Rini, Abdellatif El Khlifi
  Cc: Rob Herring, U-Boot Mailing List, vishnu.banavath,
	xueliang.zhong, nd, Rui Miguel Silva

On Tue, Apr 12, 2022 at 7:01 AM Tom Rini <trini@konsulko.com> wrote:
>
> On Tue, Apr 12, 2022 at 12:43:15PM +0100, Abdellatif El Khlifi wrote:
> > On Thu, Apr 07, 2022 at 08:58:11AM -0400, Tom Rini wrote:
> > > On Thu, Apr 07, 2022 at 01:54:24PM +0100, Abdellatif El Khlifi wrote:
> > > > On Wed, Apr 06, 2022 at 03:47:11PM -0400, Tom Rini wrote:
> > > > > On Tue, Mar 29, 2022 at 04:16:53PM +0100, abdellatif.elkhlifi@arm.com wrote:
> > > > > > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > > >
> > > > > > This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> > > > > >
> > > > > > FF-A support is generic by design and can be used by any Arm platform.
> > > > > >
> > > > > > The features added are as follows:
> > > > > >
> > > > > > 1/ FF-A device driver
> > > > > > 2/ armffa command
> > > > > > 3/ FF-A Sandbox driver
> > > > > > 4/ FF-A Sandbox test cases
> > > > > > 5/ FF-A MM communication
> > > > > >
> > > > > >
> > > > > > The suggested design sees FF-A as a data bus allowing data exchange with the firmware
> > > > > > running under TrustZone HW (such as Optee). The same approach was followed in the
> > > > > > FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> > > > > >
> > > > > > u-boot boards using FF-A can provide a device tree node in a <board>-u-boot.dtsi file.
> > > > > > Since the node can not be hosted in Linux device tree, we suggest using u-boot device tree.
> > > > >
> > > > > Why can't the node be in the upstream tree?  It should be, so that it
> > > > > can be shared between all users.  Especially since there's in-Linux
> > > > > users?
> > > > >
> > > > > --
> > > > > Tom
> > > >
> > > > Linux already has an FF-A bus driver and doesn't use a device tree node for FF-A.
> > > >
> > > > The Linux driver registers FF-A as a bus:
> > > >
> > > > int arm_ffa_bus_init(void)
> > > > {
> > > >   return bus_register(&ffa_bus_type);
> > > > }
> > > >
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211
> > > >
> > > > So, there is no user for the node in Linux. That's why we suggest hosting the node in the u-boot device tree (a u-boot.dtsi file)
> > >
> > > OK, but you can still push it upstream as it's not required to have an
> > > in tree user.
> >
> > During the review of Corstone-1000 patchset, Rui Silva had a discussion with the Linux device tree maintainer
> > (Rob Herring). Rob is not in favour of an FFA node in the kernel device tree. This is why we are including the FFA node
> > in u-boot device tree (u-boot.dtsi files).

Sigh. There is not a 'kernel device tree' and a 'u-boot device tree'.
There is only 1. For SystemReadyIR compliance, that is a hard
requirement.

> I'm a bit confused now, can you please link to the kernel thread?  Or
> Rob, can you chime in here please?

The FFA DT binding was rejected in favor of making FFA discoverable.
The FFA spec was amended to address that. DT is only for what we
failed to make discoverable. For hardware, we're stuck with it. We
shouldn't repeat that for software interfaces.

Rob

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-04-12 13:28           ` Rob Herring
@ 2022-04-13 14:20             ` Abdellatif El Khlifi
  2022-04-13 16:46               ` Tom Rini
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-04-13 14:20 UTC (permalink / raw)
  To: Rob Herring
  Cc: ilias.apalodimas, achin.gupta, sudeep.holla, sjg,
	abdellatif.elkhlifi, rui.silva, trini, vishnu.banavath,
	xueliang.zhong, u-boot, nd

On Tue, Apr 12, 2022 at 08:28:42AM -0500, Rob Herring wrote:
> On Tue, Apr 12, 2022 at 7:01 AM Tom Rini <trini@konsulko.com> wrote:
> >
> > On Tue, Apr 12, 2022 at 12:43:15PM +0100, Abdellatif El Khlifi wrote:
> > > On Thu, Apr 07, 2022 at 08:58:11AM -0400, Tom Rini wrote:
> > > > On Thu, Apr 07, 2022 at 01:54:24PM +0100, Abdellatif El Khlifi wrote:
> > > > > On Wed, Apr 06, 2022 at 03:47:11PM -0400, Tom Rini wrote:
> > > > > > On Tue, Mar 29, 2022 at 04:16:53PM +0100, abdellatif.elkhlifi@arm.com wrote:
> > > > > > > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > > > >
> > > > > > > This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> > > > > > >
> > > > > > > FF-A support is generic by design and can be used by any Arm platform.
> > > > > > >
> > > > > > > The features added are as follows:
> > > > > > >
> > > > > > > 1/ FF-A device driver
> > > > > > > 2/ armffa command
> > > > > > > 3/ FF-A Sandbox driver
> > > > > > > 4/ FF-A Sandbox test cases
> > > > > > > 5/ FF-A MM communication
> > > > > > >
> > > > > > >
> > > > > > > The suggested design sees FF-A as a data bus allowing data exchange with the firmware
> > > > > > > running under TrustZone HW (such as Optee). The same approach was followed in the
> > > > > > > FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> > > > > > >
> > > > > > > u-boot boards using FF-A can provide a device tree node in a <board>-u-boot.dtsi file.
> > > > > > > Since the node can not be hosted in Linux device tree, we suggest using u-boot device tree.
> > > > > >
> > > > > > Why can't the node be in the upstream tree?  It should be, so that it
> > > > > > can be shared between all users.  Especially since there's in-Linux
> > > > > > users?
> > > > > >
> > > > > > --
> > > > > > Tom
> > > > >
> > > > > Linux already has an FF-A bus driver and doesn't use a device tree node for FF-A.
> > > > >
> > > > > The Linux driver registers FF-A as a bus:
> > > > >
> > > > > int arm_ffa_bus_init(void)
> > > > > {
> > > > >   return bus_register(&ffa_bus_type);
> > > > > }
> > > > >
> > > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211
> > > > >
> > > > > So, there is no user for the node in Linux. That's why we suggest hosting the node in the u-boot device tree (a u-boot.dtsi file)
> > > >
> > > > OK, but you can still push it upstream as it's not required to have an
> > > > in tree user.
> > >
> > > During the review of Corstone-1000 patchset, Rui Silva had a discussion with the Linux device tree maintainer
> > > (Rob Herring). Rob is not in favour of an FFA node in the kernel device tree. This is why we are including the FFA node
> > > in u-boot device tree (u-boot.dtsi files).
> 
> Sigh. There is not a 'kernel device tree' and a 'u-boot device tree'.
> There is only 1. For SystemReadyIR compliance, that is a hard
> requirement.
> 
> > I'm a bit confused now, can you please link to the kernel thread?  Or
> > Rob, can you chime in here please?
> 
> The FFA DT binding was rejected in favor of making FFA discoverable.
> The FFA spec was amended to address that. DT is only for what we
> failed to make discoverable. For hardware, we're stuck with it. We
> shouldn't repeat that for software interfaces.
> 
> Rob

Guys,

Since we can not add an FFA node in the device tree, we will make FFA a discoverable bus.
So, we will manually create the udevice, binding it to the driver and probing it.
Manually means directly calling device_bind and device_probe APIs.

Any thoughts about this approach ?

Abdellatif


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-04-13 14:20             ` Abdellatif El Khlifi
@ 2022-04-13 16:46               ` Tom Rini
  2022-04-13 17:29                 ` Sudeep Holla
  2022-08-01 19:13                 ` [PATCH 0/6] introduce Arm FF-A support Simon Glass
  0 siblings, 2 replies; 478+ messages in thread
From: Tom Rini @ 2022-04-13 16:46 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Rob Herring, ilias.apalodimas, achin.gupta, sudeep.holla, sjg,
	rui.silva, vishnu.banavath, xueliang.zhong, u-boot, nd

[-- Attachment #1: Type: text/plain, Size: 4091 bytes --]

On Wed, Apr 13, 2022 at 03:20:23PM +0100, Abdellatif El Khlifi wrote:
> On Tue, Apr 12, 2022 at 08:28:42AM -0500, Rob Herring wrote:
> > On Tue, Apr 12, 2022 at 7:01 AM Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Tue, Apr 12, 2022 at 12:43:15PM +0100, Abdellatif El Khlifi wrote:
> > > > On Thu, Apr 07, 2022 at 08:58:11AM -0400, Tom Rini wrote:
> > > > > On Thu, Apr 07, 2022 at 01:54:24PM +0100, Abdellatif El Khlifi wrote:
> > > > > > On Wed, Apr 06, 2022 at 03:47:11PM -0400, Tom Rini wrote:
> > > > > > > On Tue, Mar 29, 2022 at 04:16:53PM +0100, abdellatif.elkhlifi@arm.com wrote:
> > > > > > > > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > > > > >
> > > > > > > > This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> > > > > > > >
> > > > > > > > FF-A support is generic by design and can be used by any Arm platform.
> > > > > > > >
> > > > > > > > The features added are as follows:
> > > > > > > >
> > > > > > > > 1/ FF-A device driver
> > > > > > > > 2/ armffa command
> > > > > > > > 3/ FF-A Sandbox driver
> > > > > > > > 4/ FF-A Sandbox test cases
> > > > > > > > 5/ FF-A MM communication
> > > > > > > >
> > > > > > > >
> > > > > > > > The suggested design sees FF-A as a data bus allowing data exchange with the firmware
> > > > > > > > running under TrustZone HW (such as Optee). The same approach was followed in the
> > > > > > > > FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> > > > > > > >
> > > > > > > > u-boot boards using FF-A can provide a device tree node in a <board>-u-boot.dtsi file.
> > > > > > > > Since the node can not be hosted in Linux device tree, we suggest using u-boot device tree.
> > > > > > >
> > > > > > > Why can't the node be in the upstream tree?  It should be, so that it
> > > > > > > can be shared between all users.  Especially since there's in-Linux
> > > > > > > users?
> > > > > > >
> > > > > > > --
> > > > > > > Tom
> > > > > >
> > > > > > Linux already has an FF-A bus driver and doesn't use a device tree node for FF-A.
> > > > > >
> > > > > > The Linux driver registers FF-A as a bus:
> > > > > >
> > > > > > int arm_ffa_bus_init(void)
> > > > > > {
> > > > > >   return bus_register(&ffa_bus_type);
> > > > > > }
> > > > > >
> > > > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211
> > > > > >
> > > > > > So, there is no user for the node in Linux. That's why we suggest hosting the node in the u-boot device tree (a u-boot.dtsi file)
> > > > >
> > > > > OK, but you can still push it upstream as it's not required to have an
> > > > > in tree user.
> > > >
> > > > During the review of Corstone-1000 patchset, Rui Silva had a discussion with the Linux device tree maintainer
> > > > (Rob Herring). Rob is not in favour of an FFA node in the kernel device tree. This is why we are including the FFA node
> > > > in u-boot device tree (u-boot.dtsi files).
> > 
> > Sigh. There is not a 'kernel device tree' and a 'u-boot device tree'.
> > There is only 1. For SystemReadyIR compliance, that is a hard
> > requirement.
> > 
> > > I'm a bit confused now, can you please link to the kernel thread?  Or
> > > Rob, can you chime in here please?
> > 
> > The FFA DT binding was rejected in favor of making FFA discoverable.
> > The FFA spec was amended to address that. DT is only for what we
> > failed to make discoverable. For hardware, we're stuck with it. We
> > shouldn't repeat that for software interfaces.
> > 
> > Rob
> 
> Guys,
> 
> Since we can not add an FFA node in the device tree, we will make FFA a discoverable bus.
> So, we will manually create the udevice, binding it to the driver and probing it.
> Manually means directly calling device_bind and device_probe APIs.
> 
> Any thoughts about this approach ?

How is it both discoverable and doesn't have a device tree node, in the
kernel?

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-04-13 16:46               ` Tom Rini
@ 2022-04-13 17:29                 ` Sudeep Holla
  2022-04-15 12:27                   ` [PATCH v2 " abdellatif.elkhlifi
  2022-08-01 19:13                 ` [PATCH 0/6] introduce Arm FF-A support Simon Glass
  1 sibling, 1 reply; 478+ messages in thread
From: Sudeep Holla @ 2022-04-13 17:29 UTC (permalink / raw)
  To: Tom Rini
  Cc: Abdellatif El Khlifi, Sudeep Holla, Rob Herring,
	ilias.apalodimas, achin.gupta, sjg, rui.silva, vishnu.banavath,
	xueliang.zhong, u-boot

On Wed, Apr 13, 2022 at 12:46:07PM -0400, Tom Rini wrote:
> On Wed, Apr 13, 2022 at 03:20:23PM +0100, Abdellatif El Khlifi wrote:

[...]

> > Since we can not add an FFA node in the device tree, we will make FFA a discoverable bus.
> > So, we will manually create the udevice, binding it to the driver and probing it.
> > Manually means directly calling device_bind and device_probe APIs.
> >
> > Any thoughts about this approach ?
>
> How is it both discoverable and doesn't have a device tree node, in the
> kernel?
>

I don't clearly understand your query here fully. Generally if some h/w
is discoverable, then we don't need to have device node in the DT as it
may result in conflicts.

In this we can query f/w to check if a particular feature is implemented
or not before we initialise the FF-A bus. One we discover the partitions
we add devices for each and the individual device and associated driver
gets probed based on UUID.

I have neither seen the u-boot implementation nor fully understand how
device/driver model differs from the kernel one to comment on details.
I am happy to provide any more details if required.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 6/6] arm_ffa: introduce FF-A MM communication
  2022-03-29 15:16 ` [PATCH 6/6] arm_ffa: introduce FF-A MM communication abdellatif.elkhlifi
@ 2022-04-14 19:54   ` Ilias Apalodimas
  2022-09-26 10:56     ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2022-04-14 19:54 UTC (permalink / raw)
  To: abdellatif.elkhlifi; +Cc: u-boot, nd, trini, Gowtham Suresh Kumar

Hi Abdellatif, 

Can you please keep me cc'ed in future revisions?

On Tue, Mar 29, 2022 at 04:16:59PM +0100, abdellatif.elkhlifi@arm.com wrote:
> From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> 
> Add MM communication support using FF-A transport
> 
> FF-A MM communication allows exchanging data with StandAlonneMM
> or smm-gateway secure partitions which run in OP-TEE.
> 
> An MM shared buffer and a door bell event are used to exchange
> this data.
> 
> The data is used by EFI services such as GetVariable()/SetVariable()
>  and copied from the communication buffer to the MM shared buffer.
> 
> The secure partition is notified about availability of data in the
>  MM shared buffer by an FF-A message (door bell).
> 
> On such event, MM SP can read the data and updates the MM shared
>  buffer with the response data.
> 
> The response data is copied back to the communication buffer and
>  consumed by the EFI subsystem.

What I am missing from all this is a description on how to test this and
what's needed in OP-TEE and EDK2.

Unless I am reading this wrong, there is a "new" Secure Partition that will
handle both the efi variables (along with all the EFI rules you need to update
those and the crypto checks you need for authenticated variables). But StMM
includes the hardware drivers as well. How is that handled in the SP
context?

> 
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
> Cc: Tom Rini <trini@konsulko.com>
> ---
>  arch/arm/cpu/armv8/cache.S        |  16 ++
>  arch/arm/cpu/armv8/cache_v8.c     |   3 +-
>  include/mm_communication.h        |   4 +-
>  lib/efi_loader/Kconfig            |  14 +-
>  lib/efi_loader/efi_variable_tee.c | 294 +++++++++++++++++++++++++++++-
>  5 files changed, 321 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S
> index d1cee23437..bdbe89e0c5 100644
> --- a/arch/arm/cpu/armv8/cache.S
> +++ b/arch/arm/cpu/armv8/cache.S
> @@ -21,7 +21,11 @@
>   * x1: 0 clean & invalidate, 1 invalidate only
>   * x2~x9: clobbered
>   */
> +#ifdef CONFIG_ARM_FFA_TRANSPORT
> +.pushsection .text.efi_runtime, "ax"
> +#else
>  .pushsection .text.__asm_dcache_level, "ax"
> +#endif
>  ENTRY(__asm_dcache_level)
>  	lsl	x12, x0, #1
>  	msr	csselr_el1, x12		/* select cache level */
> @@ -65,7 +69,11 @@ ENDPROC(__asm_dcache_level)
>   *
>   * flush or invalidate all data cache by SET/WAY.
>   */
> +#ifdef CONFIG_ARM_FFA_TRANSPORT
> +.pushsection .text.efi_runtime, "ax"
> +#else
>  .pushsection .text.__asm_dcache_all, "ax"
> +#endif
>  ENTRY(__asm_dcache_all)
>  	mov	x1, x0
>  	dsb	sy
> @@ -109,7 +117,11 @@ ENTRY(__asm_flush_dcache_all)
>  ENDPROC(__asm_flush_dcache_all)
>  .popsection
>  
> +#ifdef CONFIG_ARM_FFA_TRANSPORT
> +.pushsection .text.efi_runtime, "ax"
> +#else
>  .pushsection .text.__asm_invalidate_dcache_all, "ax"
> +#endif
>  ENTRY(__asm_invalidate_dcache_all)
>  	mov	x0, #0x1
>  	b	__asm_dcache_all
> @@ -182,7 +194,11 @@ ENTRY(__asm_invalidate_icache_all)
>  ENDPROC(__asm_invalidate_icache_all)
>  .popsection
>  
> +#ifdef CONFIG_ARM_FFA_TRANSPORT
> +.pushsection .text.efi_runtime, "ax"
> +#else
>  .pushsection .text.__asm_invalidate_l3_dcache, "ax"
> +#endif
>  WEAK(__asm_invalidate_l3_dcache)
>  	mov	x0, #0			/* return status as success */
>  	ret
> diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
> index 3de18c7675..187a4497a7 100644
> --- a/arch/arm/cpu/armv8/cache_v8.c
> +++ b/arch/arm/cpu/armv8/cache_v8.c
> @@ -9,6 +9,7 @@
>  
>  #include <common.h>
>  #include <cpu_func.h>
> +#include <efi_loader.h>
>  #include <hang.h>
>  #include <log.h>
>  #include <asm/cache.h>
> @@ -425,7 +426,7 @@ __weak void mmu_setup(void)
>  /*
>   * Performs a invalidation of the entire data cache at all levels
>   */
> -void invalidate_dcache_all(void)
> +void __efi_runtime invalidate_dcache_all(void)
>  {
>  	__asm_invalidate_dcache_all();
>  	__asm_invalidate_l3_dcache();
> diff --git a/include/mm_communication.h b/include/mm_communication.h
> index e65fbde60d..bb99190956 100644
> --- a/include/mm_communication.h
> +++ b/include/mm_communication.h
> @@ -123,7 +123,7 @@ struct __packed efi_mm_communicate_header {
>   *
>   * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_HEADER.
>   */
> -struct smm_variable_communicate_header {
> +struct __packed smm_variable_communicate_header {

Why is this converted to packed?

>  	efi_uintn_t  function;
>  	efi_status_t ret_status;
>  	u8           data[];
> @@ -145,7 +145,7 @@ struct smm_variable_communicate_header {
>   * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
>   *
>   */
> -struct smm_variable_access {
> +struct __packed smm_variable_access {

Ditto

>  	efi_guid_t  guid;
>  	efi_uintn_t data_size;
>  	efi_uintn_t name_size;
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index 28657f50c9..0d69133595 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
>  	  stored as file /ubootefi.var on the EFI system partition.
>  
>  config EFI_MM_COMM_TEE
> -	bool "UEFI variables storage service via OP-TEE"
> -	depends on OPTEE
> +	bool "UEFI variables storage service via the trusted world"
> +	depends on OPTEE || ARM_FFA_TRANSPORT
>  	help
> +	  The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
> +	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> +	  When using the u-boot FF-A  driver, StandAlonneMM and smm-gateway are supported.
> +
>  	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
>  	  variable related operations to that. The application will verify,
>  	  authenticate and store the variables on an RPMB.
>  
> +	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> +	  operations to the MM SP running under Optee in the trusted world.
> +	  A door bell mechanism is used to notify the SP when there is data in the shared
> +	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
> +	  the door bell event.
> +

The naming is a bit misleading imho.  FF-A is the transport mechanism between the
secure and non-secure world. You may as well have FF-A along with OP-TEE.
That doesn't automatically mean the SP is used instead of StMM.

This code is complicated already, I don't think we want the additional
ifdefery.  Wouldn't it be better to have this discover to what kind of
protocol (e.g FF-A vs SMC calling conventions) it talks to?  SPs are
discoverable,  so we could reason about those as well without asking the
user to understand Arm protocol internals. 

>  endchoice
>  
>  config EFI_VARIABLES_PRESEED
> diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> index dfef18435d..3d01985662 100644
> --- a/lib/efi_loader/efi_variable_tee.c
> +++ b/lib/efi_loader/efi_variable_tee.c
> @@ -15,6 +15,53 @@
>  #include <malloc.h>
>  #include <mm_communication.h>
>  
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +
> +#include <arm_ffa_helper.h>
> +#include <cpu_func.h>
> +#include <mapmem.h>
> +
> +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> +
> +#include <linux/sizes.h>
> +#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
> +
> +#endif
> +
> +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> +
> +/*
> + * shared buffer physical address used for communication between
> + * u-boot and the MM SP
> + */
> +#define FFA_SHARED_MM_BUFFER_ADDR	(0x023F8000)

Can you explain what this is used for ?

> +
> +#endif
> +
> +/* MM return codes */
> +#define MM_SUCCESS (0)
> +
> +#define ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64 (0xC4000061)
> +#define ARM_SVC_ID_SP_EVENT_COMPLETE ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64
> +
> +#ifndef MM_SP_UUID_DATA
> +
> +/* MM SP UUID binary data (little-endian format) */
> +#define MM_SP_UUID_DATA	\
> +	0xed, 0x32, 0xd5, 0x33,	\
> +	0x99, 0xe6, 0x42, 0x09,	\
> +	0x9c, 0xc0, 0x2d, 0x72,	\
> +	0xcd, 0xd9, 0x98, 0xa7

[...]

> +
> +	/* Announce there is data in the shared buffer */
> +
> +	ffa_ret = ffa_notify_mm_sp();
> +	if (ffa_ret)
> +		unmap_sysmem(virt_shared_buf);

There are several calls around on runtime code which call functions not
marked as runtime.  This will just crash when called.

> +
> +	switch (ffa_ret) {
> +	case 0:
> +	{
> +		ulong rx_data_size;
> +		/* Copy the MM SP response from the shared buffer to the communication buffer */
> +		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> +			sizeof(efi_guid_t) +
> +			sizeof(size_t);
> +
> +		if (rx_data_size > comm_buf_size) {
> +			efi_memcpy_runtime(comm_buf, virt_shared_buf, comm_buf_size);
> +			unmap_sysmem(virt_shared_buf);
> +			return EFI_BUFFER_TOO_SMALL;
> +		}
> +
> +		efi_memcpy_runtime(comm_buf, virt_shared_buf, rx_data_size);
> +		unmap_sysmem(virt_shared_buf);
> +
> +		return EFI_SUCCESS;
> +	}
> +	case -EINVAL:
> +		return EFI_DEVICE_ERROR;
> +	case -EPERM:
> +		return EFI_INVALID_PARAMETER;
> +	case -EACCES:
> +		return EFI_ACCESS_DENIED;
> +	case -EBUSY:
> +		return EFI_OUT_OF_RESOURCES;
> +	default:
> +		return EFI_ACCESS_DENIED;
> +	}
> +}
> +#endif
> +
> +/**
> + * mm_communicate() - Adjust the communication buffer to the MM SP and send
>   * it to OP-TEE
>   *
> - * @comm_buf:		locally allocted communcation buffer
> + * @comm_buf:		locally allocated communication buffer
>   * @dsize:		buffer size
> + *
> + * The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
> + * The comm_buf format is the same for both partitions.
> + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> + * When using the u-boot FF-A  driver, StandAlonneMM and smm-gateway are supported.
> + *
>   * Return:		status code
>   */
> -static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> +static efi_status_t __efi_runtime mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  {
>  	efi_status_t ret;
>  	struct efi_mm_communicate_header *mm_hdr;
> @@ -162,9 +432,16 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
>  	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
>  
> +	#if (IS_ENABLED(CONFIG_OPTEE))
>  	ret = optee_mm_communicate(comm_buf, dsize);
> +	#elif (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +	ret = ffa_mm_communicate(comm_buf, dsize);
> +	#endif
>  	if (ret != EFI_SUCCESS) {
> -		log_err("%s failed!\n", __func__);
> +		/* No need for showing a log here. mm_communicate failure happens
> +		 * when getVariable() is called with data size set to 0.
> +		 * This is not expected so no log shown.
> +		 */

It can also fail on normal cases were the size is != 0

>  		return ret;
>  	}
>  
> @@ -258,6 +535,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
>  		goto out;
>  	}
>  	*size = var_payload->size;
> +
> +	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
> +			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
> +				MM_VARIABLE_COMMUNICATE_SIZE;
> +	#endif
> +
>  	/*
>  	 * There seems to be a bug in EDK2 miscalculating the boundaries and
>  	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> @@ -697,7 +981,7 @@ void efi_variables_boot_exit_notify(void)
>  		ret = EFI_NOT_FOUND;
>  
>  	if (ret != EFI_SUCCESS)
> -		log_err("Unable to notify StMM for ExitBootServices\n");
> +		log_err("Unable to notify the MM partition for ExitBootServices\n");
>  	free(comm_buf);
>  
>  	/*
> -- 
> 2.17.1
> 

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v2 0/6] introduce Arm FF-A support
  2022-04-13 17:29                 ` Sudeep Holla
@ 2022-04-15 12:27                   ` abdellatif.elkhlifi
  2022-04-15 12:27                     ` [PATCH v2 1/6] arm_ffa: introduce Arm FF-A low-level driver abdellatif.elkhlifi
                                       ` (6 more replies)
  0 siblings, 7 replies; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-04-15 12:27 UTC (permalink / raw)
  To: u-boot
  Cc: sudeep.holla, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	robh, sjg, trini, vishnu.banavath, xueliang.zhong, nd

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

This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).

FF-A support is generic by design and can be used by any Arm platform.

The features added are as follows:
    
1/ FF-A bus driver
2/ armffa command
3/ FF-A Sandbox driver
4/ FF-A Sandbox test cases
5/ FF-A MM communication

The suggested design considers FF-A as a discoverable bus.
The Secure World is considered as one entity to communicate with using the FF-A bus.
FF-A communication is handled by one device and one instance (the bus).
This FF-A driver takes care of all the interactions between Normal world
and Secure World.

The Secure World firmware runs  under TrustZone HW (such as Optee). The same approach was followed in the
FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))

Cc: Tom Rini <trini@konsulko.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Vishnu Banavath <vishnu.banavath@arm.com>
 
Abdellatif El Khlifi (6):
  arm_ffa: introduce Arm FF-A low-level driver
  arm_ffa: introduce armffa command
  arm_ffa: introduce the FF-A Sandbox driver
  arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: introduce FF-A MM communication

 MAINTAINERS                           |   15 +
 arch/arm/cpu/armv8/cache.S            |   16 +
 arch/arm/cpu/armv8/cache_v8.c         |    3 +-
 arch/arm/cpu/armv8/smccc-call.S       |   27 +
 arch/arm/lib/asm-offsets.c            |    6 +
 cmd/Kconfig                           |   10 +
 cmd/Makefile                          |    2 +
 cmd/armffa.c                          |  266 +++++
 common/board_r.c                      |    7 +
 configs/sandbox64_defconfig           |    2 +
 configs/sandbox_defconfig             |    2 +
 doc/arch/sandbox.rst                  |    1 +
 drivers/Kconfig                       |    2 +
 drivers/Makefile                      |    1 +
 drivers/arm-ffa/Kconfig               |   34 +
 drivers/arm-ffa/Makefile              |    7 +
 drivers/arm-ffa/arm-ffa-uclass.c      |  103 ++
 drivers/arm-ffa/arm_ffa_prv.h         |  193 ++++
 drivers/arm-ffa/core.c                | 1384 +++++++++++++++++++++++++
 drivers/arm-ffa/sandbox.c             |  669 ++++++++++++
 drivers/arm-ffa/sandbox_arm_ffa_prv.h |  131 +++
 include/arm_ffa.h                     |  197 ++++
 include/arm_ffa_helper.h              |   45 +
 include/dm/uclass-id.h                |    1 +
 include/linux/arm-smccc.h             |   28 +-
 include/mm_communication.h            |    4 +-
 include/sandbox_arm_ffa.h             |   31 +
 include/sandbox_arm_ffa_helper.h      |   26 +
 lib/Kconfig                           |    1 +
 lib/Makefile                          |    1 +
 lib/arm-ffa/Kconfig                   |    6 +
 lib/arm-ffa/Makefile                  |    9 +
 lib/arm-ffa/arm_ffa_helper.c          |  188 ++++
 lib/arm-ffa/sandbox_arm_ffa_helper.c  |   23 +
 lib/efi_loader/Kconfig                |   14 +-
 lib/efi_loader/efi_boottime.c         |   17 +
 lib/efi_loader/efi_variable_tee.c     |  281 ++++-
 test/cmd/Makefile                     |    1 +
 test/cmd/armffa.c                     |   33 +
 test/cmd/armffa.h                     |   13 +
 test/dm/Makefile                      |    1 +
 test/dm/ffa.c                         |  418 ++++++++
 test/dm/ffa.h                         |   22 +
 43 files changed, 4230 insertions(+), 11 deletions(-)
 create mode 100644 cmd/armffa.c
 create mode 100644 drivers/arm-ffa/Kconfig
 create mode 100644 drivers/arm-ffa/Makefile
 create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/arm-ffa/core.c
 create mode 100644 drivers/arm-ffa/sandbox.c
 create mode 100644 drivers/arm-ffa/sandbox_arm_ffa_prv.h
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_helper.h
 create mode 100644 include/sandbox_arm_ffa.h
 create mode 100644 include/sandbox_arm_ffa_helper.h
 create mode 100644 lib/arm-ffa/Kconfig
 create mode 100644 lib/arm-ffa/Makefile
 create mode 100644 lib/arm-ffa/arm_ffa_helper.c
 create mode 100644 lib/arm-ffa/sandbox_arm_ffa_helper.c
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/cmd/armffa.h
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/dm/ffa.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v2 1/6] arm_ffa: introduce Arm FF-A low-level driver
  2022-04-15 12:27                   ` [PATCH v2 " abdellatif.elkhlifi
@ 2022-04-15 12:27                     ` abdellatif.elkhlifi
  2022-05-13 14:23                       ` Ilias Apalodimas
  2022-05-13 14:40                       ` Jens Wiklander
  2022-04-15 12:27                     ` [PATCH v2 2/6] arm_ffa: introduce armffa command abdellatif.elkhlifi
                                       ` (5 subsequent siblings)
  6 siblings, 2 replies; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-04-15 12:27 UTC (permalink / raw)
  To: u-boot
  Cc: sudeep.holla, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	robh, sjg, trini, vishnu.banavath, xueliang.zhong, nd

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

Add the driver implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A)
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology. This driver uses SMC32 calling convention.

In u-boot FF-A design, FF-A is considered as a discoverable bus.
The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver provides helper FF-A interfaces for user layers.
These helper functions allow clients to pass data and select the
FF-A function to use for the communication with secure world.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
---
 MAINTAINERS                      |    8 +
 arch/arm/cpu/armv8/smccc-call.S  |   27 +
 arch/arm/lib/asm-offsets.c       |    6 +
 common/board_r.c                 |    7 +
 drivers/Kconfig                  |    2 +
 drivers/Makefile                 |    1 +
 drivers/arm-ffa/Kconfig          |   27 +
 drivers/arm-ffa/Makefile         |    6 +
 drivers/arm-ffa/arm-ffa-uclass.c |   64 ++
 drivers/arm-ffa/arm_ffa_prv.h    |  193 +++++
 drivers/arm-ffa/core.c           | 1349 ++++++++++++++++++++++++++++++
 include/arm_ffa.h                |  190 +++++
 include/arm_ffa_helper.h         |   45 +
 include/dm/uclass-id.h           |    1 +
 include/linux/arm-smccc.h        |   28 +-
 lib/Kconfig                      |    1 +
 lib/Makefile                     |    1 +
 lib/arm-ffa/Kconfig              |    6 +
 lib/arm-ffa/Makefile             |    8 +
 lib/arm-ffa/arm_ffa_helper.c     |  188 +++++
 lib/efi_loader/efi_boottime.c    |   17 +
 21 files changed, 2174 insertions(+), 1 deletion(-)
 create mode 100644 drivers/arm-ffa/Kconfig
 create mode 100644 drivers/arm-ffa/Makefile
 create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/arm-ffa/core.c
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_helper.h
 create mode 100644 lib/arm-ffa/Kconfig
 create mode 100644 lib/arm-ffa/Makefile
 create mode 100644 lib/arm-ffa/arm_ffa_helper.c

diff --git a/MAINTAINERS b/MAINTAINERS
index aca97cd2a3..efa17206b8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -232,6 +232,14 @@ F:	board/CZ.NIC/
 F:	configs/turris_*_defconfig
 F:	include/configs/turris_*.h
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	drivers/arm-ffa/
+F:	include/arm_ffa.h
+F:	include/arm_ffa_helper.h
+F:	lib/arm-ffa/
+
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..9a6aebf194 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
@@ -45,3 +47,28 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+	.macro FFASMCCC instr
+	.cfi_startproc
+	\instr	#0
+	ldr	x9, [sp]
+	stp	x0, x1, [x9, #ARM_SMCCC_RES_X0_OFFS]
+	stp	x2, x3, [x9, #ARM_SMCCC_RES_X2_OFFS]
+	stp	x4, x5, [x9, #ARM_SMCCC_RES_X4_OFFS]
+	stp	x6, x7, [x9, #ARM_SMCCC_RES_X6_OFFS]
+	ret
+	.cfi_endproc
+	.endm
+
+/*
+ * void arm_ffa_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
+ *		  unsigned long a3, unsigned long a4, unsigned long a5,
+ *		  unsigned long a6, unsigned long a7, struct arm_smccc_res *res)
+ */
+ENTRY(__arm_ffa_smccc_smc)
+	FFASMCCC	smc
+ENDPROC(__arm_ffa_smccc_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 22fd541f9a..02a4a42fe6 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,8 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * (C) Copyright 2022 ARM Limited
  */
 
 #include <common.h>
@@ -115,6 +117,10 @@ int main(void)
 #ifdef CONFIG_ARM_SMCCC
 	DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+	DEFINE(ARM_SMCCC_RES_X4_OFFS, offsetof(struct arm_smccc_res, a4));
+	DEFINE(ARM_SMCCC_RES_X6_OFFS, offsetof(struct arm_smccc_res, a6));
+#endif
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
 #endif
diff --git a/common/board_r.c b/common/board_r.c
index b92c1bb0be..bb5f1d0aa6 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -62,6 +62,10 @@
 #include <asm-generic/gpio.h>
 #include <efi_loader.h>
 
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+#include <arm_ffa_helper.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -771,6 +775,9 @@ static init_fnc_t init_sequence_r[] = {
 	INIT_FUNC_WATCHDOG_RESET
 	initr_net,
 #endif
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+	ffa_helper_bus_discover,
+#endif
 #ifdef CONFIG_POST
 	initr_post,
 #endif
diff --git a/drivers/Kconfig b/drivers/Kconfig
index b26ca8cf70..e83c23789d 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
 
 source "drivers/adc/Kconfig"
 
+source "drivers/arm-ffa/Kconfig"
+
 source "drivers/ata/Kconfig"
 
 source "drivers/axi/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 4e7cf28440..6671d2a604 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -107,6 +107,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
new file mode 100644
index 0000000000..23815534c4
--- /dev/null
+++ b/drivers/arm-ffa/Kconfig
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC if ARM64
+	select LIB_UUID
+	select ARM_FFA_TRANSPORT_HELPERS
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  This driver is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In u-boot FF-A design, FF-A is considered as a discoverable bus.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  This FF-A driver takes care of all the interactions between Normal world
+	  and Secure World.
diff --git a/drivers/arm-ffa/Makefile b/drivers/arm-ffa/Makefile
new file mode 100644
index 0000000000..7bc9a336a9
--- /dev/null
+++ b/drivers/arm-ffa/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+#
+
+obj-y += arm-ffa-uclass.o core.o
diff --git a/drivers/arm-ffa/arm-ffa-uclass.c b/drivers/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..2439f87586
--- /dev/null
+++ b/drivers/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <arm_ffa.h>
+#include <errno.h>
+#include <log.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+UCLASS_DRIVER(ffa) = {
+	.name		= "ffa",
+	.id		= UCLASS_FFA,
+};
+
+/**
+ * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher
+ * @func_id:	The FF-A function to be used
+ * @func_data:  Pointer to the FF-A function arguments
+ *				container structure. This also includes
+ *				pointers to the returned data needed by
+ *				clients.
+ *
+ * This runtime function passes the FF-A function ID and its arguments to
+ * the FF-A driver dispatcher.
+ * This function is called by the FF-A helper functions.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int __ffa_runtime ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *func_data)
+{
+	if (!ffa_device_get_ops()->invoke_func)
+		return -EINVAL;
+
+	return ffa_device_get_ops()->invoke_func(func_id, func_data);
+}
+
+/**
+ * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
+ *
+ * This boot time function makes sure the FF-A bus is discoverable.
+ * Then, the arm_ffa device is probed and ready to use.
+ * This function is called automatically at initcalls
+ * level (after u-boot relocation).
+ *
+ * Arm FF-A transport is implemented through arm_ffa u-boot device managing the FF-A
+ * communication.
+ * All FF-A clients should use the arm_ffa device to use the FF-A transport.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int ffa_bus_discover(void)
+{
+	return ffa_get_device();
+}
diff --git a/drivers/arm-ffa/arm_ffa_prv.h b/drivers/arm-ffa/arm_ffa_prv.h
new file mode 100644
index 0000000000..44f258addb
--- /dev/null
+++ b/drivers/arm-ffa/arm_ffa_prv.h
@@ -0,0 +1,193 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <arm_ffa.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <dm/read.h>
+
+/*
+ * This header is private. It is exclusively used by the FF-A driver
+ */
+
+/* FF-A core driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* FF-A driver version definitions */
+
+#define MAJOR_VERSION_MASK		GENMASK(30, 16)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/* The FF-A SMC function prototype definition */
+
+typedef void (*invoke_ffa_fn_t)(unsigned long a0, unsigned long a1,
+			unsigned long a2, unsigned long a3, unsigned long a4,
+			unsigned long a5, unsigned long a6, unsigned long a7,
+			struct arm_smccc_res *res);
+
+/**
+ * enum ffa_conduit - Arm FF-A conduits supported by the Arm FF-A driver
+ * Currently only SMC32 is supported.
+ */
+enum ffa_conduit {
+	FFA_CONDUIT_SMC = 0,
+};
+
+/**
+ * FFA_DECLARE_ARGS - FF-A functions local variables
+ * @a0-a7:	local variables used to set registers x0-x7
+ * @res:	the structure hosting the FF-A function return data
+ *
+ * A helper macro for declaring local variables for the FF-A functions  arguments.
+ * The x0-x7 registers are used to exchange data with the secure world.
+ * But, only the bottom 32-bit of thes registers contains the data.
+ */
+#define FFA_DECLARE_ARGS \
+	unsigned long a0 = 0; \
+	unsigned long a1 = 0; \
+	unsigned long a2 = 0; \
+	unsigned long a3 = 0; \
+	unsigned long a4 = 0; \
+	unsigned long a5 = 0; \
+	unsigned long a6 = 0; \
+	unsigned long a7 = 0; \
+	struct arm_smccc_res res = {0}
+
+/* FF-A error codes */
+#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_INTERRUPTED				(-5)
+#define FFA_ERR_STAT_DENIED				(-6)
+#define FFA_ERR_STAT_RETRY				(-7)
+#define FFA_ERR_STAT_ABORTED				(-8)
+
+/**
+ * struct ffa_features_desc - FF-A functions features
+ * @func_id:	FF-A function
+ * @field1:	features read from register w2
+ * @field2:	features read from register w3
+ *
+ * Data structure describing the features of the  FF-A functions queried by
+ * FFA_FEATURES
+ */
+struct ffa_features_desc {
+	u32 func_id;
+	u32 field1;
+	u32 field2;
+};
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/*
+ * Number of the FF-A interfaces features descriptors
+ * currently only FFA_RXTX_MAP descriptor is supported
+ */
+#define FFA_FEATURE_DESC_CNT (1)
+
+/**
+ * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ *
+ * Data structure hosting the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	u64 rxbuf; /* virtual address */
+	u64 txbuf; /* virtual address */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @UUID:	UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	union ffa_partition_uuid UUID;
+};
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * This data structure contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* virtual address */
+};
+
+/**
+ * struct 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
+ * @conduit:	The selected conduit
+ * @invoke_ffa_fn:	The function executing the FF-A function
+ * @features:	Table of the FF-A functions having features
+ *
+ * The driver data structure hosting all resident data.
+ */
+struct ffa_prvdata {
+	struct udevice *dev;
+	u32 fwk_version;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+	enum ffa_conduit conduit;
+	invoke_ffa_fn_t invoke_ffa_fn;
+	struct ffa_features_desc features[FFA_FEATURE_DESC_CNT];
+};
+
+#endif
diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c
new file mode 100644
index 0000000000..09e4eb753a
--- /dev/null
+++ b/drivers/arm-ffa/core.c
@@ -0,0 +1,1349 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include "arm_ffa_prv.h"
+#include <asm/global_data.h>
+#include <asm/io.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 <log.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <string.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * The device private data structure containing all the resident
+ * data read from secure world
+ */
+struct ffa_prvdata __ffa_runtime_data ffa_priv_data = {0};
+
+/*
+ * Driver functions
+ */
+
+/**
+ * ffa_get_device - create, bind and probe the arm_ffa device
+ *
+ * This boot time function makes sure the arm_ffa device is
+ * created, bound to this driver, probed and ready to use.
+ * Arm FF-A transport is implemented through a single u-boot
+ * device managing the FF-A bus (arm_ffa).
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int ffa_get_device(void)
+{
+	int ret;
+
+	if (ffa_priv_data.dev)
+		return FFA_ERR_STAT_SUCCESS;
+
+	ret = device_bind(dm_root(),
+			  DM_DRIVER_GET(arm_ffa),
+			  FFA_DRV_NAME,
+			  NULL,
+			  ofnode_null(),
+			  &ffa_priv_data.dev);
+	if (ret) {
+		ffa_priv_data.dev = NULL;
+		return ret;
+	}
+
+	/* The FF-A bus discovery succeeds when probing is successful */
+	ret = device_probe(ffa_priv_data.dev);
+	if (ret) {
+		ffa_err("can not probe  the device");
+		device_unbind(ffa_priv_data.dev);
+		ffa_priv_data.dev = NULL;
+		return ret;
+	}
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_get_version - FFA_VERSION handler function
+ *
+ * This is the boot time function that implements FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_get_version(void)
+{
+	u16 major, minor;
+
+	FFA_DECLARE_ARGS;
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	a0 = FFA_VERSION;
+	a1 = FFA_VERSION_1_0;
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
+
+	if (res.a0 == FFA_ERR_STAT_NOT_SUPPORTED) {
+		ffa_err("A Firmware Framework implementation does not exist");
+		return -EOPNOTSUPP;
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
+		ffa_info("Versions are compatible ");
+
+		ffa_priv_data.fwk_version = res.a0;
+
+		return FFA_ERR_STAT_SUCCESS;
+	}
+
+	ffa_info("Versions are incompatible ");
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id - FFA_ID_GET handler function
+ *
+ * This is the boot time function that implements FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(void)
+{
+	FFA_DECLARE_ARGS;
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	a0 = FFA_ID_GET;
+
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
+			ffa_err("This function is not implemented at this FF-A instance");
+			return -EOPNOTSUPP;
+		}
+
+		ffa_err("Undefined error code (%d)", ((int)res.a2));
+		return -EINVAL;
+	}
+	case FFA_SUCCESS:
+	{
+		ffa_priv_data.id = GET_SELF_ENDPOINT_ID(res.a2);
+		ffa_info("endpoint ID is %u", ffa_priv_data.id);
+
+		return FFA_ERR_STAT_SUCCESS;
+	}
+	default:
+	{
+		ffa_err("Undefined response function (0x%lx)", res.a0);
+		return -EINVAL;
+	}
+	}
+}
+
+/**
+ * ffa_get_features_desc - returns the features descriptor of the specified
+ *						FF-A function
+ * @func_id:	the FF-A function which the features are to be retrieved
+ *
+ * This is a boot time function that searches the features descriptor of the
+ * specified FF-A function
+ *
+ * Return:
+ *
+ * When found, the address of the features descriptor is returned. Otherwise, NULL.
+ */
+static struct ffa_features_desc *ffa_get_features_desc(u32 func_id)
+{
+	u32 desc_idx;
+
+	/*
+	 * search for the descriptor of the selected FF-A interface
+	 */
+	for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
+		if (ffa_priv_data.features[desc_idx].func_id == func_id)
+			return &ffa_priv_data.features[desc_idx];
+
+	return NULL;
+}
+
+/**
+ * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP
+ *							argument
+ *
+ * This is the boot time function that implements FFA_FEATURES FF-A function
+ * to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features(void)
+{
+	FFA_DECLARE_ARGS;
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	a0 = FFA_FEATURES;
+	a1 = FFA_RXTX_MAP;
+
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
+			ffa_err("FFA_RXTX_MAP is not implemented at this FF-A instance");
+			return -EOPNOTSUPP;
+		}
+
+		ffa_err("Undefined error code (%d)", ((int)res.a2));
+		return -EINVAL;
+	}
+	case FFA_SUCCESS:
+	{
+		u32 desc_idx;
+
+		/*
+		 * search for an empty descriptor
+		 */
+		for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
+			if (!ffa_priv_data.features[desc_idx].func_id) {
+				/*
+				 * populate the descriptor with
+				 * the interface features data
+				 */
+				ffa_priv_data.features[desc_idx].func_id =
+					FFA_RXTX_MAP;
+				ffa_priv_data.features[desc_idx].field1 =
+					res.a2;
+
+				ffa_info("FFA_RXTX_MAP features data 0x%lx",
+					 res.a2);
+
+				return FFA_ERR_STAT_SUCCESS;
+			}
+
+		ffa_err("Cannot save FFA_RXTX_MAP features data. Descriptors table full");
+		return -ENOBUFS;
+	}
+	default:
+	{
+		ffa_err("Undefined response function (0x%lx)",
+			res.a0);
+		return -EINVAL;
+	}
+	}
+}
+
+/**
+ * ffa_get_rxtx_buffers_pages_cnt - reads from the features data descriptors
+ *						the minimum number of pages in each of the RX/TX
+ *						buffers
+ * @buf_4k_pages: Pointer to the minimum number of pages
+ *
+ * This is the boot time function that  returns the minimum number of pages
+ *  in each of the RX/TX buffers
+ *
+ * Return:
+ *
+ * buf_4k_pages points to the returned number of pages
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_buffers_pages_cnt(size_t *buf_4k_pages)
+{
+	struct ffa_features_desc *desc = NULL;
+
+	if (!buf_4k_pages)
+		return -EINVAL;
+
+	desc = ffa_get_features_desc(FFA_RXTX_MAP);
+	if (!desc)
+		return -EINVAL;
+
+	switch (desc->field1) {
+	case RXTX_4K:
+		*buf_4k_pages = 1;
+		break;
+	case RXTX_16K:
+		*buf_4k_pages = 4;
+		break;
+	case RXTX_64K:
+		*buf_4k_pages = 16;
+		break;
+	default:
+		ffa_err("RX/TX buffer size not supported");
+		return -EINVAL;
+	}
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_free_rxtx_buffers - frees the RX/TX buffers
+ * @buf_4k_pages: the minimum number of pages in each of the RX/TX
+ *			  buffers
+ *
+ * This is the boot time function used to free the RX/TX buffers
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_free_rxtx_buffers(size_t buf_4k_pages)
+{
+	efi_status_t free_rxbuf_ret, free_txbuf_ret;
+
+	ffa_info("Freeing RX/TX buffers");
+
+	free_rxbuf_ret = efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
+	free_txbuf_ret = efi_free_pages(ffa_priv_data.pair.txbuf, buf_4k_pages);
+
+	if (free_rxbuf_ret != EFI_SUCCESS || free_txbuf_ret != EFI_SUCCESS) {
+		ffa_err("Failed to free RX/TX buffers (rx: %lu , tx: %lu)",
+			free_rxbuf_ret,
+			free_txbuf_ret);
+		return -EINVAL;
+	}
+
+	ffa_priv_data.pair.rxbuf = 0;
+	ffa_priv_data.pair.txbuf = 0;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
+ * @buf_4k_pages: the minimum number of pages in each of the RX/TX
+ *			  buffers
+ *
+ * This is the boot time function used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(size_t buf_4k_pages)
+{
+#if CONFIG_IS_ENABLED(EFI_LOADER)
+
+	efi_status_t efi_ret;
+	void *virt_txbuf;
+	void *virt_rxbuf;
+
+	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
+		 buf_4k_pages);
+
+	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				     EFI_BOOT_SERVICES_DATA,
+				     buf_4k_pages,
+				     &ffa_priv_data.pair.rxbuf);
+
+	if (efi_ret != EFI_SUCCESS) {
+		ffa_priv_data.pair.rxbuf = 0;
+		ffa_err("Failure to allocate RX buffer (EFI error: 0x%lx)",
+			efi_ret);
+
+		return -ENOBUFS;
+	}
+
+	ffa_info("RX buffer at virtual address 0x%llx",
+		 ffa_priv_data.pair.rxbuf);
+
+	virt_rxbuf = (void *)ffa_priv_data.pair.rxbuf;
+
+	/*
+	 * make sure the buffer is clean before use
+	 */
+	memset(virt_rxbuf, 0, buf_4k_pages * SZ_4K);
+
+	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				     EFI_RUNTIME_SERVICES_DATA,
+				     buf_4k_pages,
+				     &ffa_priv_data.pair.txbuf);
+
+	if (efi_ret != EFI_SUCCESS) {
+		efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
+		ffa_priv_data.pair.rxbuf = 0;
+		ffa_priv_data.pair.txbuf = 0;
+		ffa_err("Failure to allocate the TX buffer (EFI error: 0x%lx)"
+			, efi_ret);
+
+		return -ENOBUFS;
+	}
+
+	ffa_info("TX buffer at virtual address 0x%llx",
+		 ffa_priv_data.pair.txbuf);
+
+	virt_txbuf = (void *)ffa_priv_data.pair.txbuf;
+
+	/*
+	 * make sure the buffer is clean before use
+	 */
+	memset(virt_txbuf, 0, buf_4k_pages * SZ_4K);
+
+	return FFA_ERR_STAT_SUCCESS;
+
+#else
+	return -ENOBUFS;
+#endif
+}
+
+/**
+ * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
+ * @buf_4k_pages: the minimum number of pages in each of the RX/TX
+ *			  buffers
+ *
+ * This is the boot time function that implements FFA_RXTX_MAP FF-A function
+ * to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers(size_t buf_4k_pages)
+{
+	int ret;
+
+	FFA_DECLARE_ARGS;
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	ret = ffa_alloc_rxtx_buffers(buf_4k_pages);
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	a0 = FFA_RXTX_MAP;
+	a1 = ffa_priv_data.pair.txbuf;
+	a2 = ffa_priv_data.pair.rxbuf;
+	a3 = buf_4k_pages;
+
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		switch (((int)res.a2)) {
+		case FFA_ERR_STAT_INVALID_PARAMETERS:
+			ffa_err("One or more fields in input parameters is incorrectly encoded");
+			ret = -EPERM;
+			break;
+		case FFA_ERR_STAT_NO_MEMORY:
+			ffa_err("Not enough memory");
+			ret = -ENOMEM;
+			break;
+		case FFA_ERR_STAT_DENIED:
+			ffa_err("Buffer pair already registered");
+			ret = -EACCES;
+			break;
+		case FFA_ERR_STAT_NOT_SUPPORTED:
+			ffa_err("This function is not implemented at this FF-A instance");
+			ret = -EOPNOTSUPP;
+			break;
+		default:
+			ffa_err("Undefined error (%d)",
+				((int)res.a2));
+			ret = -EINVAL;
+		}
+		break;
+	}
+	case FFA_SUCCESS:
+		ffa_info("RX/TX buffers mapped");
+		return FFA_ERR_STAT_SUCCESS;
+	default:
+		ffa_err("Undefined response function (0x%lx)",
+			res.a0);
+		ret = -EINVAL;
+	}
+
+	ffa_free_rxtx_buffers(buf_4k_pages);
+
+	return ret;
+}
+
+/**
+ * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
+ *
+ * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_unmap_rxtx_buffers(void)
+{
+	FFA_DECLARE_ARGS;
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	a0 = FFA_RXTX_UNMAP;
+	a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id);
+
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
+			panic("[FFA] FFA_RXTX_UNMAP is not implemented at this FF-A instance\n");
+		else if (((int)res.a2) == FFA_ERR_STAT_INVALID_PARAMETERS)
+			panic("[FFA] There is no buffer pair registered on behalf of the caller\n");
+		else
+			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
+	}
+	case FFA_SUCCESS:
+	{
+		size_t buf_4k_pages = 0;
+		int ret;
+
+		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
+		if (ret != FFA_ERR_STAT_SUCCESS)
+			panic("[FFA] RX/TX buffers unmapped but failure in getting pages count\n");
+
+		ret = ffa_free_rxtx_buffers(buf_4k_pages);
+		if (ret != FFA_ERR_STAT_SUCCESS)
+			panic("[FFA] RX/TX buffers unmapped but failure in freeing the memory\n");
+
+		ffa_info("RX/TX buffers unmapped and memory freed");
+
+		return FFA_ERR_STAT_SUCCESS;
+	}
+	default:
+		panic("[FFA] Undefined response function (0x%lx)", res.a0);
+	}
+}
+
+/**
+ * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
+ *
+ * This is the boot time function that invokes FFA_RX_RELEASE FF-A function
+ * to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer(void)
+{
+	FFA_DECLARE_ARGS;
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	a0 = FFA_RX_RELEASE;
+
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
+			panic("[FFA] FFA_RX_RELEASE is not implemented at this FF-A instance\n");
+		else if (((int)res.a2) == FFA_ERR_STAT_DENIED)
+			panic("[FFA] Caller did not have ownership of the RX buffer\n");
+		else
+			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
+	}
+	case FFA_SUCCESS:
+		return FFA_ERR_STAT_SUCCESS;
+
+	default:
+		panic("[FFA] Undefined response function (0x%lx)\n", res.a0);
+	}
+}
+
+/**
+ * ffa_uuid_are_identical - checks whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * This is a boot time function used by ffa_read_partitions_info to search
+ * for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+int ffa_uuid_are_identical(const union ffa_partition_uuid *uuid1,
+			   const union ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return (!memcmp(uuid1, uuid2, sizeof(union ffa_partition_uuid)));
+}
+
+/**
+ * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
+ *							and saves it in the private structure
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * This is the boot time function that reads the partitions information
+ * returned by the FFA_PARTITION_INFO_GET and saves it in the private
+ * data structure.
+ *
+ * Return:
+ *
+ * The private data structure is updated with the partition(s) information
+ * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(u32 count, union ffa_partition_uuid *part_uuid)
+{
+	if (!count) {
+		ffa_err("No partition detected");
+		return -ENODATA;
+	}
+
+	ffa_info("Reading partitions data from the RX buffer");
+
+#if CONFIG_IS_ENABLED(EFI_LOADER)
+
+	if (!part_uuid) {
+		/*
+		 * querying information of all partitions
+		 */
+		u64 data_pages;
+		u64 data_bytes;
+		efi_status_t efi_ret;
+		size_t buf_4k_pages = 0;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+		int ret;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+		data_pages = efi_size_in_pages(data_bytes);
+
+		/*
+		 * get the RX buffer size in pages
+		 */
+		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
+		if (ret != FFA_ERR_STAT_SUCCESS) {
+			ffa_err("Can not get the RX buffer size (error %d)", ret);
+			return ret;
+		}
+
+		if (data_pages > buf_4k_pages) {
+			ffa_err("Partitions data size exceeds the RX buffer size:");
+			ffa_err("    Sizes in pages: data %llu , RX buffer %lu ",
+				data_pages,
+				buf_4k_pages);
+
+			return -ENOMEM;
+		}
+
+		efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+					     EFI_RUNTIME_SERVICES_DATA,
+					     data_pages,
+					     (u64 *)&ffa_priv_data.partitions.descs);
+
+		if (efi_ret != EFI_SUCCESS) {
+			ffa_priv_data.partitions.descs = NULL;
+
+			ffa_err("Cannot  allocate partitions data buffer (EFI error 0x%lx)",
+				efi_ret);
+
+			return -ENOBUFS;
+		}
+
+		/*
+		 * make sure the buffer is clean before use
+		 */
+		memset(ffa_priv_data.partitions.descs, 0,
+		       data_pages * SZ_4K);
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data.pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			ffa_priv_data.partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			ffa_info("Partition ID %x : info cached",
+				 ffa_priv_data.partitions.descs[desc_idx].info.id);
+		}
+
+		ffa_priv_data.partitions.count = count;
+
+		ffa_info("%d partition(s) found and cached", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data.pair.rxbuf;
+
+		/*
+		 * search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/*
+			 * search the current ID in the cached partitions
+			 */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < ffa_priv_data.partitions.count;
+			     cached_desc_idx++) {
+				/*
+				 * save the UUID
+				 */
+				if (ffa_priv_data.partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					ffa_priv_data.partitions.descs[cached_desc_idx].UUID =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+#else
+#warning "arm_ffa: reading FFA_PARTITION_INFO_GET data not implemented"
+#endif
+
+	return  FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET
+ *							and saves partitions data
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * This is the boot time function that executes the FFA_PARTITION_INFO_GET
+ * to query the partitions data. Then, it calls ffa_read_partitions_info
+ * to save the data in the private data structure.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(union ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	unsigned long a0 = 0;
+	union ffa_partition_uuid query_uuid = {0};
+	unsigned long a5 = 0;
+	unsigned long a6 = 0;
+	unsigned long a7 = 0;
+	struct arm_smccc_res res = {0};
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	a0 = FFA_PARTITION_INFO_GET;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	}
+
+	ffa_priv_data.invoke_ffa_fn(a0, query_uuid.words.a1, query_uuid.words.a2,
+				    query_uuid.words.a3, query_uuid.words.a4,
+				    a5, a6, a7, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		switch (((int)res.a2)) {
+		case FFA_ERR_STAT_INVALID_PARAMETERS:
+			ffa_err("Unrecognized UUID");
+			return -EPERM;
+		case FFA_ERR_STAT_NO_MEMORY:
+			ffa_err("Results cannot fit in RX buffer of the caller");
+			return -ENOMEM;
+		case FFA_ERR_STAT_DENIED:
+			ffa_err("Callee is not in a state to handle this request");
+			return -EACCES;
+		case FFA_ERR_STAT_NOT_SUPPORTED:
+			ffa_err("This function is not implemented at this FF-A instance");
+			return -EOPNOTSUPP;
+		case FFA_ERR_STAT_BUSY:
+			ffa_err("RX buffer of the caller is not free");
+			return -EBUSY;
+		default:
+			ffa_err("Undefined error (%d)", ((int)res.a2));
+			return -EINVAL;
+		}
+	}
+	case FFA_SUCCESS:
+	{
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info(res.a2, part_uuid);
+			if (ret)
+				ffa_err("Failed to read partition(s) data , error (%d)", ret);
+		}
+
+		/*
+		 * return the SP count
+		 */
+		if (part_uuid) {
+			if (!ret)
+				*pcount = res.a2;
+			else
+				*pcount = 0;
+		}
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the secure world
+		 */
+		ret = ffa_release_rx_buffer();
+
+		if (!part_uuid && !res.a2) {
+			ffa_err("[FFA] no partition installed in the system");
+			return -ENODEV;
+		}
+
+		return ret;
+	}
+	default:
+		ffa_err("Undefined response function (0x%lx)", res.a0);
+		return  -EINVAL;
+	}
+}
+
+/**
+ * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
+ * @func_data: Pointer to the FF-A function arguments container structure.
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@data0_size: UUID size
+ *	@data0: pointer to the UUID (little endian)
+ *	@data1_size: size of the number of partitions
+ *				variable
+ *	@data1: pointer to the number of partitions
+ *			 variable. The variable will be set
+ *			 by the driver
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@data0_size: UUID size
+ *	@data0: pointer to the UUID (little endian)
+ *	@data1_size: size of the SPs information buffer
+ *	@data1: pointer to SPs information buffer
+ *		(allocated by the client).
+ *		The buffer will be filled by the driver
+ *
+ * This is the boot time function that queries the secure partition data from
+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * When invoked through a client request, ffa_get_partitions_info should be
+ * called twice. First call is to get from the driver the number of secure
+ * partitions (SPs) associated to a particular UUID.
+ * Then, the caller (client) allocates the buffer to host the SPs data and
+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
+ * buffer.
+ *
+ * To achieve the mechanism described above, ffa_get_partitions_info uses the
+ * following functions:
+ *		ffa_read_partitions_info
+ *		ffa_query_partitions_info
+ *
+ * Return:
+ *
+ * @data1: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer, the buffer will be
+ * filled by the driver.
+ *
+ * On success FFA_ERR_STAT_SUCCESS is returned. Otherwise, failure
+ */
+static int ffa_get_partitions_info(struct ffa_interface_data *func_data)
+{
+	/*
+	 * fill_data:
+	 * 0: return the SP count
+	 * 1: fill SP data and return it to the caller
+	 * -1: undefined mode
+	 */
+	int fill_data = -1;
+	u32 desc_idx, client_desc_idx;
+	union ffa_partition_uuid *part_uuid;
+	u32 client_desc_max_cnt;
+	u32 parts_found = 0;
+
+	if (!func_data) {
+		ffa_err("No function data provided");
+		return -EINVAL;
+	}
+
+	if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs)
+		panic("[FFA] No partition installed\n");
+
+	if (func_data->data0_size == sizeof(union ffa_partition_uuid) &&
+	    func_data->data0 &&
+	    func_data->data1_size == sizeof(u32) &&
+	    func_data->data1) {
+		/*
+		 * data0 (in): pointer to UUID
+		 * data1 (in): pointer to SP count
+		 * Out: SP count returned in the count variable pointed by data1
+		 */
+
+		fill_data = 0;
+
+		ffa_info("Preparing for checking partitions count");
+
+	} else if ((func_data->data0_size == sizeof(union ffa_partition_uuid)) &&
+		   func_data->data0 &&
+		   (func_data->data1_size >= sizeof(struct ffa_partition_info)) &&
+		   !(func_data->data1_size % sizeof(struct ffa_partition_info)) &&
+		   func_data->data1) {
+		/*
+		 * data0 (in): pointer to UUID
+		 * data1 (in): pointer to SPs descriptors buffer
+		 *             (created by the client)
+		 * Out: SPs descriptors returned in the buffer
+		 *      pointed by data1
+		 */
+
+		fill_data = 1;
+
+		client_desc_idx = 0;
+
+		/*
+		 * number of empty descriptors preallocated by the caller
+		 */
+		client_desc_max_cnt =
+			func_data->data1_size / sizeof(struct ffa_partition_info);
+
+		ffa_info("Preparing for filling partitions info");
+
+	} else {
+		ffa_err("Invalid function arguments provided");
+		return -EINVAL;
+	}
+
+	part_uuid = (union ffa_partition_uuid *)func_data->data0;
+
+	ffa_info("Searching partitions using the provided UUID");
+
+	/*
+	 * search in the cached partitions
+	 */
+	for (desc_idx = 0;
+	     desc_idx < ffa_priv_data.partitions.count;
+	     desc_idx++) {
+		if (ffa_uuid_are_identical(&ffa_priv_data.partitions.descs[desc_idx].UUID,
+					   part_uuid)) {
+			ffa_info("Partition ID %x matches the provided UUID",
+				 ffa_priv_data.partitions.descs[desc_idx].info.id);
+
+			parts_found++;
+
+			if (fill_data) {
+				/*
+				 * trying to fill the partition info in data1
+				 */
+
+				if (client_desc_idx < client_desc_max_cnt) {
+					((struct ffa_partition_info *)
+					 func_data->data1)[client_desc_idx++] =
+						ffa_priv_data.partitions.descs[desc_idx].info;
+					continue;
+				}
+
+				ffa_err("Failed to fill the current descriptor client buffer full");
+				return -ENOBUFS;
+			}
+		}
+	}
+
+	if (!parts_found) {
+		int ret;
+
+		ffa_info("No partition found. Querying framework ...");
+
+		ret = ffa_query_partitions_info(part_uuid, &parts_found);
+
+		if (ret == FFA_ERR_STAT_SUCCESS) {
+			if (!fill_data) {
+				*((u32 *)func_data->data1) = parts_found;
+
+				ffa_info("Number of partition(s) found matching the UUID: %d",
+					 parts_found);
+			} else {
+				/*
+				 * we want to read SPs info
+				 */
+
+				/*
+				 * If SPs data filled, retry searching SP info again
+				 */
+				if (parts_found)
+					ret = ffa_get_partitions_info(func_data);
+				else
+					ret = -ENODATA;
+			}
+		}
+
+		return ret;
+	}
+
+	/* partition(s) found */
+	if (!fill_data)
+		*((u32 *)func_data->data1) = parts_found;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_cache_partitions_info - Queries and saves all secure partitions data
+ *
+ * This is a boot time function that invokes FFA_PARTITION_INFO_GET FF-A
+ * function to query from secure world all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in the
+ * resident private data structure and we keep the UUID field empty
+ * (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * This function is called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(void)
+{
+	return ffa_query_partitions_info(NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @func_data: Pointer to the FF-A function arguments container structure.
+ *					The passed arguments:
+ *						@data0_size: partition ID size
+ *						@data0: pointer to the partition ID
+ *						@data1_size: exchanged data size
+ *						@data1: pointer to the data buffer preallocated by
+ *								the client (in/out)
+ *
+ * This is the runtime function that implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 20 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int __ffa_runtime ffa_msg_send_direct_req(struct ffa_interface_data
+						 *func_data)
+{
+	u16 dst_part_id;
+	unsigned long a0 = 0;
+	unsigned long a1 = 0;
+	unsigned long a2 = 0;
+	struct ffa_send_direct_data *msg;
+	struct arm_smccc_res res = {0};
+
+	if (!ffa_priv_data.invoke_ffa_fn)
+		return -ENODEV;
+
+	if (!func_data)
+		return -EINVAL;
+
+	/* No partition installed */
+	if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs)
+		return -ENODEV;
+
+	/* Undefined interface parameters */
+	if (func_data->data0_size != sizeof(u16) ||
+	    !func_data->data0 ||
+	    func_data->data1_size != FFA_MSG_SEND_DIRECT_MAX_SIZE ||
+	    !func_data->data1)
+		return -EINVAL;
+
+	dst_part_id = *((u16 *)func_data->data0);
+	msg = func_data->data1;
+
+	a0 = FFA_MSG_SEND_DIRECT_REQ;
+
+	a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id) |
+		PREP_PART_ENDPOINT_ID(dst_part_id);
+
+	ffa_priv_data.invoke_ffa_fn(a0, a1, a2,
+				    msg->a3,
+				    msg->a4,
+				    msg->a5,
+				    msg->a6,
+				    msg->a7,
+				    &res);
+
+	while (res.a0 == FFA_INTERRUPT)
+		ffa_priv_data.invoke_ffa_fn(FFA_RUN, res.a1,
+					    0, 0, 0, 0, 0, 0,
+					    &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		switch (((int)res.a2)) {
+		case FFA_ERR_STAT_INVALID_PARAMETERS:
+			/* Invalid endpoint ID or non-zero reserved register */
+			return -EPERM;
+		case FFA_ERR_STAT_ABORTED:
+			/* Message target ran into unexpected error and has aborted */
+			return -ECONNABORTED;
+		case FFA_ERR_STAT_DENIED:
+			/* Callee is not in a state to handle this request */
+			return -EACCES;
+		case FFA_ERR_STAT_NOT_SUPPORTED:
+			/* This function is not implemented at this FF-A instance */
+			return -EOPNOTSUPP;
+		case FFA_ERR_STAT_BUSY:
+			/* Message target is busy */
+			return -EBUSY;
+		default:
+			/* Undefined error */
+			return -ENXIO;
+		}
+	}
+	case FFA_SUCCESS:
+
+		/* Message sent with no response */
+		return FFA_ERR_STAT_SUCCESS;
+
+	case FFA_MSG_SEND_DIRECT_RESP:
+
+		/*
+		 * Message sent with response
+		 * extract the 32-bit wide return data
+		 */
+		msg->a3 = (u32)res.a3;
+		msg->a4 = (u32)res.a4;
+		msg->a5 = (u32)res.a5;
+		msg->a6 = (u32)res.a6;
+		msg->a7 = (u32)res.a7;
+
+		return FFA_ERR_STAT_SUCCESS;
+
+	default:
+		/* Undefined response function */
+		return -ENOENT;
+	}
+}
+
+/**
+ * invoke_ffa_drv_api - The driver dispatcher function
+ * @func_id:	The FF-A function to be used
+ * @func_data:  Pointer to the FF-A function arguments container
+ *					structure. This also includes pointers to the
+ *					returned data needed by clients.
+ * The dispatcher is a runtime function that selects the FF-A function handler
+ * based on the input FF-A function ID.
+ * The input arguments are passed to the handler function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int __ffa_runtime invoke_ffa_drv_api(u32 func_id,
+				     struct ffa_interface_data *func_data)
+{
+	if (!ffa_priv_data.dev)
+		return -ENODEV;
+
+	switch (func_id) {
+	case FFA_PARTITION_INFO_GET:
+		return ffa_get_partitions_info(func_data);
+	case FFA_RXTX_UNMAP:
+		return ffa_unmap_rxtx_buffers();
+	case FFA_MSG_SEND_DIRECT_REQ:
+		return ffa_msg_send_direct_req(func_data);
+	default:
+		/* Undefined FF-A interface */
+		return -EINVAL;
+	}
+}
+
+/**
+ * ffa_set_conduit - Set the conduit
+ *
+ * This boot time function clears the private data structure and sets the conduit
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_set_conduit(void)
+{
+	ffa_priv_data.conduit = FFA_CONDUIT_SMC;
+
+	ffa_priv_data.invoke_ffa_fn = arm_ffa_smccc_smc;
+
+	ffa_info("Conduit is SMC");
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_probe - The driver probe function
+ * @dev:	the arm_ffa device
+ *
+ * Probing is done at boot time and triggered by the uclass device discovery.
+ * At probe level the following actions are done:
+ *	- setting the conduit
+ *	- querying the FF-A framework version
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of the specified FF-A calls
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in the resident private data structure.
+ *
+ * The probe will fail if either FF-A framework is not detected or the
+ * FF-A requests are not behaving correctly. This ensures that the
+ * driver is not installed and its operations are not exported to the clients.
+ * However, once the driver is successfully probed and an FF-A anomaly is
+ * detected when clients invoke the driver operations, the driver cause
+ * u-boot to panic because the client would not know what to do in such conditions.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_probe(struct udevice *dev)
+{
+	int ret;
+	size_t buf_4k_pages = 0;
+
+	ret = ffa_set_conduit();
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_get_version();
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_get_endpoint_id();
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features();
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers(buf_4k_pages);
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_cache_partitions_info();
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		ffa_free_rxtx_buffers(buf_4k_pages);
+		return ret;
+	}
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_drv_ops - The driver operations runtime structure
+ * @invoke_func:	The driver dispatcher
+ */
+struct ffa_ops __ffa_runtime_data ffa_drv_ops = {
+	.invoke_func = invoke_ffa_drv_api
+};
+
+/**
+ * ffa_device_get_ops - driver operations getter
+ *
+ * Return:
+ * This runtime function returns a pointer to the driver operations structure
+ */
+const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void)
+{
+	return &ffa_drv_ops;
+}
+
+/**
+ * Declaring the arm_ffa driver under UCLASS_FFA
+ */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.probe		= ffa_probe,
+};
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..98db01ee72
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,190 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/arm-smccc.h>
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * Macros for displaying logs
+ */
+
+#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
+#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
+
+/*
+ * The driver operations success error code
+ */
+#define FFA_ERR_STAT_SUCCESS				(0)
+
+#if CONFIG_IS_ENABLED(EFI_LOADER)
+
+#include <efi_loader.h>
+
+/*
+ * __ffa_runtime_data and __ffa_runtime - controls whether data/code are
+ * available after calling the EFI ExitBootServices service.
+ * Data/code tagged with these keywords are resident (available at boot time and
+ * at runtime)
+ */
+
+#define __ffa_runtime_data __efi_runtime_data
+#define __ffa_runtime __efi_runtime
+
+#else
+
+#define __ffa_runtime_data
+#define __ffa_runtime
+
+#endif
+
+/*
+ * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
+ */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)	FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+
+#define FFA_VERSION				FFA_SMC_32(0x63)
+#define FFA_ID_GET				FFA_SMC_32(0x69)
+#define FFA_FEATURES				FFA_SMC_32(0x64)
+#define FFA_PARTITION_INFO_GET				FFA_SMC_32(0x68)
+#define FFA_RXTX_MAP				FFA_SMC_32(0x66)
+#define FFA_RXTX_UNMAP				FFA_SMC_32(0x67)
+#define FFA_RX_RELEASE				FFA_SMC_32(0x65)
+#define FFA_MSG_SEND_DIRECT_REQ				FFA_SMC_32(0x6F)
+#define FFA_MSG_SEND_DIRECT_RESP				FFA_SMC_32(0x70)
+#define FFA_RUN				FFA_SMC_32(0x6D)
+#define FFA_ERROR				FFA_SMC_32(0x60)
+#define FFA_SUCCESS				FFA_SMC_32(0x61)
+#define FFA_INTERRUPT				FFA_SMC_32(0x62)
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct  __packed ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @a3-a7:	Data read/written from/to w3-w7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+struct __packed ffa_send_direct_data {
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+	u32 a5; /* w5 */
+	u32 a6; /* w6 */
+	u32 a7; /* w7 */
+};
+
+#define FFA_MSG_SEND_DIRECT_MAX_SIZE (sizeof(struct ffa_send_direct_data))
+
+/* UUID data size */
+#define UUID_SIZE (16)
+
+/*
+ * union ffa_partition_uuid - Data union hosting the UUID
+ *							transmitted by FFA_PARTITION_INFO_GET
+ * @words:	data structure giving 32-bit words access to the UUID data
+ * @bytes:	data structure giving byte access to the UUID data
+ *
+ * The structure holds little-endian UUID data.
+ */
+union ffa_partition_uuid {
+	struct __packed words {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+	} words;
+	u8 bytes[UUID_SIZE];
+};
+
+/**
+ * struct ffa_interface_data - generic FF-A interface data structure used to exchange
+ *							data between user layers and the 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 user layers can pass various types of data with different sizes.
+ * The driver internal functions can detect the nature of this data, verfy compliance
+ * then execute the request when appropriate.
+ */
+struct ffa_interface_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 */
+};
+
+/**
+ * struct ffa_ops - The driver operations structure
+ * @invoke_func:	function pointer to the invoke function
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is resident.
+ */
+struct ffa_ops {
+	/* the driver dispatcher */
+	int (*invoke_func)(u32 func_id, struct ffa_interface_data *func_data);
+};
+
+/**
+ * The device driver and the Uclass driver public functions
+ */
+
+/**
+ * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher
+ */
+int __ffa_runtime ffa_get_invoke_func(u32 func_id,
+				      struct ffa_interface_data *func_data);
+
+/**
+ * ffa_device_get_ops - driver operations getter
+ */
+const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void);
+
+/**
+ * ffa_get_device - create, bind and probe the arm_ffa device
+ */
+int ffa_get_device(void);
+
+/**
+ * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
+ */
+int ffa_bus_discover(void);
+#endif
diff --git a/include/arm_ffa_helper.h b/include/arm_ffa_helper.h
new file mode 100644
index 0000000000..1cf68748f0
--- /dev/null
+++ b/include/arm_ffa_helper.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_HELPER_H
+#define __ARM_FFA_HELPER_H
+
+#include <arm_ffa.h>
+
+/*
+ * This header is public. Including this header provides all data structures
+ * and definitions needed by clients to use the FF-A transport driver
+ *
+ * It also provides helper functions allowing to pass data and invoke  FF-A functions
+ */
+
+/**
+ * ffa_helper_get_partitions_info - Wrapper function for FFA_PARTITION_INFO_GET
+ */
+int ffa_helper_get_partitions_info(struct ffa_interface_data *func_data);
+
+/**
+ * ffa_helper_unmap_rxtx_buffers - Wrapper function for FFA_RXTX_UNMAP
+ */
+int ffa_helper_unmap_rxtx_buffers(void);
+
+/**
+ * ffa_helper_msg_send_direct_req - Wrapper function for
+ *								FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ */
+int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data
+						 *func_data);
+
+/**
+ * ffa_helper_bus_discover - Wrapper function for FF-A bus discovery
+ */
+int ffa_helper_bus_discover(void);
+
+/**
+ * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
+ */
+int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin);
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 0e26e1d138..a1181b8f48 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -52,6 +52,7 @@ enum uclass_id {
 	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
 	UCLASS_GPIO,		/* Bank of general-purpose I/O pins */
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 7f2be23394..d58c7c104b 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -57,13 +59,17 @@
 #include <linux/types.h>
 /**
  * struct arm_smccc_res - Result from SMC/HVC call
- * @a0-a3 result values from registers 0 to 3
+ * @a0-a7 result values from registers 0 to 7
  */
 struct arm_smccc_res {
 	unsigned long a0;
 	unsigned long a1;
 	unsigned long a2;
 	unsigned long a3;
+	unsigned long a4;
+	unsigned long a5;
+	unsigned long a6;
+	unsigned long a7;
 };
 
 /**
@@ -113,6 +119,26 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
 			unsigned long a5, unsigned long a6, unsigned long a7,
 			struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
 
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+/**
+ * __arm_ffa_smccc_smc() - make SMC calls used for FF-A transport
+ * @a0-a7: arguments passed in 64-bit registers x0 to x7
+ * @res: result values from 64-bit registers x0 to x7
+ *
+ * This function is used to make SMC calls following SMC32 Calling Convention.
+ * The content of the supplied parameters is copied to registers x0 to x7 prior
+ * to the SMC instruction. The SMC call return data is 32-bit data read from
+ * registers x0 tp x7.
+ */
+asmlinkage void __arm_ffa_smccc_smc(unsigned long a0, unsigned long a1,
+				    unsigned long a2, unsigned long a3, unsigned long a4,
+				    unsigned long a5, unsigned long a6, unsigned long a7,
+				    struct arm_smccc_res *res);
+
+#define arm_ffa_smccc_smc __arm_ffa_smccc_smc
+
+#endif
+
 #define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
 
 #define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
diff --git a/lib/Kconfig b/lib/Kconfig
index effe735365..9006e8d44c 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -845,6 +845,7 @@ config SMBIOS_PARSER
 source lib/efi/Kconfig
 source lib/efi_loader/Kconfig
 source lib/optee/Kconfig
+source lib/arm-ffa/Kconfig
 
 config TEST_FDTDEC
 	bool "enable fdtdec test"
diff --git a/lib/Makefile b/lib/Makefile
index 13fe5fb7a4..36f67cd94e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_EFI) += efi/
 obj-$(CONFIG_EFI_LOADER) += efi_driver/
 obj-$(CONFIG_EFI_LOADER) += efi_loader/
 obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/
+obj-$(CONFIG_ARM_FFA_TRANSPORT_HELPERS) += arm-ffa/
 obj-$(CONFIG_LZMA) += lzma/
 obj-$(CONFIG_BZIP2) += bzip2/
 obj-$(CONFIG_TIZEN) += tizen/
diff --git a/lib/arm-ffa/Kconfig b/lib/arm-ffa/Kconfig
new file mode 100644
index 0000000000..79acbc5a8f
--- /dev/null
+++ b/lib/arm-ffa/Kconfig
@@ -0,0 +1,6 @@
+config ARM_FFA_TRANSPORT_HELPERS
+	bool "Enable interface helpers for Arm Firmware Framework for Armv8-A"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  User layers call FF-A interfaces using helper functions which
+	  pass the data and the FF-A function ID to the low level driver
diff --git a/lib/arm-ffa/Makefile b/lib/arm-ffa/Makefile
new file mode 100644
index 0000000000..cba625fde4
--- /dev/null
+++ b/lib/arm-ffa/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+#
+
+# This file only gets included when CONFIG_ARM_FFA_TRANSPORT_HELPERS is set
+
+obj-y += arm_ffa_helper.o
diff --git a/lib/arm-ffa/arm_ffa_helper.c b/lib/arm-ffa/arm_ffa_helper.c
new file mode 100644
index 0000000000..a291b000a7
--- /dev/null
+++ b/lib/arm-ffa/arm_ffa_helper.c
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <arm_ffa_helper.h>
+#include <uuid.h>
+
+/**
+ * ffa_helper_get_partitions_info - Wrapper function for FFA_PARTITION_INFO_GET
+ *
+ * @func_data: Pointer to the FF-A function arguments container
+ *				structure.
+ *				The passed arguments:
+ *					Mode 1: When getting from the driver the number of
+ *						secure partitions:
+ *						@data0_size: UUID size
+ *						@data0: pointer to the UUID (little endian)
+ *						@data1_size: size of the number of partitions
+ *									variable
+ *						@data1: pointer to the number of partitions
+ *								 variable. The variable will be set
+ *								 by the driver
+ *					Mode 2: When requesting the driver to return the
+ *						partitions information:
+ *						@data0_size: UUID size
+ *						@data0: pointer to the UUID (little endian)
+ *						@data1_size: size of the SPs information buffer
+ *						@data1: pointer to SPs information buffer
+ *								(allocated by the client).
+ *							The buffer will be filled by the driver
+ *
+ * This is the boot time function used by clients who wants to get from secure
+ * world the partition(s) information.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The client should use
+ * ffa_helper_get_partitions_info to pass the UUID information to the driver
+ * which uses PARTITION_INFO_GET to obtain the partition(s) information.
+ *
+ * ffa_helper_get_partitions_info should be called twice. First call is to get
+ * from the driver the number of secure partitions (SPs) associated to a
+ * particular UUID. Then, the caller (client) allocates the buffer to host the
+ * SPs data and issues a 2nd call. Then, the driver fills the SPs data in the
+ * pre-allocated buffer.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int ffa_helper_get_partitions_info(struct ffa_interface_data *func_data)
+{
+	return ffa_get_invoke_func(FFA_PARTITION_INFO_GET, func_data);
+}
+
+/**
+ * ffa_helper_unmap_rxtx_buffers - Wrapper function for FFA_RXTX_UNMAP
+ *
+ * This is the boot time function that allows clients to unmap the RX/TX
+ * buffers
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int ffa_helper_unmap_rxtx_buffers(void)
+{
+	return ffa_get_invoke_func(FFA_RXTX_UNMAP, NULL);
+}
+
+/**
+ * ffa_helper_msg_send_direct_req - Wrapper function for
+ *								FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @func_data: Pointer to the FF-A function arguments container structure.
+ * The passed arguments:
+ *	@data0_size: partition ID size
+ *	@data0: pointer to the partition ID
+ *	@data1_size: exchanged data size
+ *	@data1: pointer to the data buffer preallocated by the client (in/out)
+ *
+ * This is the runtime function that allows clients to send data to the secure
+ * world partitions. The arm_ffa driver uses FFA_MSG_SEND_DIRECT_REQ to send the
+ * data to the secure partition. The response from the secure partition is
+ * handled internally by the driver using FFA_MSG_SEND_DIRECT_RESP and returned
+ * to ffa_helper_msg_send_direct_req through @func_data
+ *
+ * The maximum size of the data that can be exchanged is 20 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * The client should pre-allocate a buffer pointed by @data1 which the size
+ * is sizeof(struct ffa_send_direct_data)
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data
+											 *func_data)
+{
+	return ffa_get_invoke_func(FFA_MSG_SEND_DIRECT_REQ, func_data);
+}
+
+/**
+ * ffa_helper_bus_discover - Wrapper function for FF-A bus discovery
+ *
+ * This boot time function should be called to discover the FF-A bus and
+ * probe the FF-A device.
+ * To achieve that, this function is called automatically at initcalls
+ * level (after u-boot relocation).
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int ffa_helper_bus_discover(void)
+{
+	return ffa_bus_discover();
+}
+
+/**
+ * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
+ * @uuid_str:	UUID string in big endian format (36 bytes wide + '/0')
+ * @uuid_bin:	preallocated 16 bytes UUID buffer in little endian format
+ *
+ * UUID binary format used by the FF-A framework (16 bytes):
+ *
+ * [LSB] 4B-2B-2B-2B-6B (little endian data fields)
+ *
+ * UUID string is 36 length of characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ * be                be      be       be      be
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a binary UUID, these endianness rules apply:
+ *     be: means the field in the string is considered a big endian hex number
+ *         and should be converted to little endian binary format
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16 = 0;
+	u32 tmp32 = 0;
+	u64 tmp64 = 0;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp32 = simple_strtoul(uuid_str, NULL, 16);
+	memcpy(uuid_bin, &tmp32, 4);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 9, NULL, 16);
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 14, NULL, 16);
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 19, NULL, 16);
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp64 = simple_strtoull(uuid_str + 24, NULL, 16);
+	memcpy(uuid_bin + 10, (char *)&tmp64, 6);
+
+	return 0;
+}
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 5bcb8253ed..cffa2c69d6 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -23,6 +23,10 @@
 #include <asm/setjmp.h>
 #include <linux/libfdt_env.h>
 
+#if defined(CONFIG_ARM_FFA_TRANSPORT)
+#include <arm_ffa_helper.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Task priority level */
@@ -2114,6 +2118,10 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 	struct efi_event *evt, *next_event;
 	efi_status_t ret = EFI_SUCCESS;
 
+#if defined(CONFIG_ARM_FFA_TRANSPORT)
+	int ffa_ret;
+#endif
+
 	EFI_ENTRY("%p, %zx", image_handle, map_key);
 
 	/* Check that the caller has read the current memory map */
@@ -2174,6 +2182,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 		dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
 	}
 
+#if defined(CONFIG_ARM_FFA_TRANSPORT)
+	/* unmap FF-A RX/TX buffers */
+	ffa_ret = ffa_helper_unmap_rxtx_buffers();
+	if (ffa_ret)
+		debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n");
+	else
+		debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
+#endif
+
 	/* Patch out unsupported runtime function */
 	efi_runtime_detach();
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v2 2/6] arm_ffa: introduce armffa command
  2022-04-15 12:27                   ` [PATCH v2 " abdellatif.elkhlifi
  2022-04-15 12:27                     ` [PATCH v2 1/6] arm_ffa: introduce Arm FF-A low-level driver abdellatif.elkhlifi
@ 2022-04-15 12:27                     ` abdellatif.elkhlifi
  2022-04-15 12:28                     ` [PATCH v2 3/6] arm_ffa: introduce the FF-A Sandbox driver abdellatif.elkhlifi
                                       ` (4 subsequent siblings)
  6 siblings, 0 replies; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-04-15 12:27 UTC (permalink / raw)
  To: u-boot
  Cc: sudeep.holla, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	robh, sjg, trini, vishnu.banavath, xueliang.zhong, nd

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

Provide armffa command showcasing the use of the FF-A driver

The armffa command allows to query secure partitions data from
the secure world and exchanging messages with the partitions.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
---
 MAINTAINERS             |   1 +
 cmd/Kconfig             |  10 ++
 cmd/Makefile            |   2 +
 cmd/armffa.c            | 266 ++++++++++++++++++++++++++++++++++++++++
 drivers/arm-ffa/Kconfig |   1 +
 5 files changed, 280 insertions(+)
 create mode 100644 cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index efa17206b8..ca2e13b9ec 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -235,6 +235,7 @@ F:	include/configs/turris_*.h
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+F:	cmd/armffa.c
 F:	drivers/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/arm_ffa_helper.h
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 516c6bbe2d..0d16e8cb14 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -823,6 +823,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the Arm FF-A driver
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index ede634d731..2905ce63cf 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,8 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
 obj-$(CONFIG_CMD_AES) += aes.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..4b74bf5f31
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <arm_ffa_helper.h>
+#include <asm/io.h>
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+
+/**
+ * do_ffa_get_singular_partition_info - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver helper function
+ * to retrieve the data.
+ * The input UUID string is expected to be in big endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_get_singular_partition_info(struct cmd_tbl *cmdtp, int flag, int argc,
+					      char *const argv[])
+{
+	struct ffa_interface_data func_data = {0};
+	u32 count = 0;
+	int ret;
+	union ffa_partition_uuid service_uuid = {0};
+	struct ffa_partition_info *parts_info;
+	u32 info_idx;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	if (ffa_uuid_str_to_bin(argv[0], (unsigned char *)&service_uuid)) {
+		ffa_err("Invalid UUID");
+		return -EINVAL;
+	}
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	func_data.data0_size = sizeof(service_uuid);
+	func_data.data0 = &service_uuid;
+	func_data.data1_size = sizeof(count);
+	func_data.data1 = &count;
+
+	ret = ffa_helper_get_partitions_info(&func_data);
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		ffa_err("Failure in querying partitions count (error code: %d)", ret);
+		return ret;
+	}
+
+	if (!count) {
+		ffa_info("No secure partition found");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	ffa_info("Pre-allocating %d partition(s) info structures", count);
+
+	func_data.data1_size = count * sizeof(struct ffa_partition_info);
+	func_data.data1 = parts_info;
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+	ret = ffa_helper_get_partitions_info(&func_data);
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		ffa_err("Failure in querying partition(s) info (error code: %d)", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * SPs found , show the partition information
+	 */
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		ffa_info("Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x",
+			 parts_info[info_idx].id,
+			 parts_info[info_idx].exec_ctxt,
+			 parts_info[info_idx].properties);
+	}
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * do_ffa_msg_send_direct_req - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function sends data to the secure partition which the ID is provided
+ * as an argument. The function uses the arm_ffa driver helper function
+ * to send data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int  do_ffa_msg_send_direct_req(struct cmd_tbl *cmdtp, int flag, int argc,
+				char *const argv[])
+{
+	struct ffa_interface_data func_data = {0};
+	struct ffa_send_direct_data msg = {0};
+	u32 pattern = 0xaabbccd0;
+	u16 part_id;
+	int ret;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	errno = 0;
+	part_id = strtoul(argv[0], NULL, 16);
+
+	if (errno) {
+		ffa_err("Invalid partition ID");
+		return -EINVAL;
+	}
+
+	/*
+	 * telling the driver which partition to use
+	 */
+	func_data.data0_size = sizeof(part_id);
+	func_data.data0 = &part_id;
+
+	/*
+	 * filling the message data
+	 */
+	msg.a3 = ++pattern;
+	msg.a4 = ++pattern;
+	msg.a5 = ++pattern;
+	msg.a6 = ++pattern;
+	msg.a7 = ++pattern;
+	func_data.data1_size = sizeof(msg);
+	func_data.data1 = &msg;
+
+	ret = ffa_helper_msg_send_direct_req(&func_data);
+	if (ret == FFA_ERR_STAT_SUCCESS) {
+		u8 cnt;
+
+		ffa_info("SP response:\n[LSB]");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u32);
+		     cnt++)
+			ffa_info("0x%x", ((u32 *)&msg)[cnt]);
+	} else {
+		ffa_err("Sending direct request error (%d)", ret);
+	}
+
+	return ret;
+}
+
+/**
+ *do_ffa_dev_list - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the devices belonging to the UCLASS_FFA
+ * class. Currently, one device is expected to show up: the arm_ffa device
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_dev_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev = NULL;
+	int i, ret;
+
+	ffa_info("arm_ffa uclass entries:");
+
+	for (i = 0, ret = uclass_first_device(UCLASS_FFA, &dev);
+	     dev;
+	     ret = uclass_next_device(&dev), i++) {
+		if (ret)
+			break;
+
+		ffa_info("entry %d - instance %08x, ops %08x, plat %08x",
+			 i,
+			 (u32)map_to_sysmem(dev),
+			 (u32)map_to_sysmem(dev->driver->ops),
+			 (u32)map_to_sysmem(dev_get_plat(dev)));
+	}
+
+	return cmd_process_error(cmdtp, ret);
+}
+
+static struct cmd_tbl armffa_commands[] = {
+	U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_get_singular_partition_info, "", ""),
+	U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_msg_send_direct_req, "", ""),
+	U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_dev_list, "", ""),
+};
+
+/**
+ * do_armffa - the armffa command main function
+ * @cmdtp:	Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function identifies which armffa subcommand to run.
+ * Then, it makes sure the arm_ffa device is probed and
+ * ready for use.
+ * Then, it runs the subcommand.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct cmd_tbl *armffa_cmd;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
+
+	argc -= 2;
+	argv += 2;
+
+	if (!armffa_cmd || argc > armffa_cmd->maxargs)
+		return CMD_RET_USAGE;
+
+	ret = ffa_helper_bus_discover();
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return cmd_process_error(cmdtp, ret);
+
+	ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
+
+	return cmd_process_error(armffa_cmd, ret);
+}
+
+U_BOOT_CMD(armffa, 4, 1, do_armffa,
+	   "Arm FF-A operations test command",
+	   "getpart <partition UUID>\n"
+	   "	 - lists the partition(s) info\n"
+	   "ping <partition ID>\n"
+	   "	 - sends a data pattern to the specified partition\n"
+	   "devlist\n"
+	   "	 - displays the arm_ffa device info\n");
diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
index 23815534c4..fa2b2fecfb 100644
--- a/drivers/arm-ffa/Kconfig
+++ b/drivers/arm-ffa/Kconfig
@@ -4,6 +4,7 @@ config ARM_FFA_TRANSPORT
 	bool "Enable Arm Firmware Framework for Armv8-A driver"
 	depends on DM && ARM64
 	select ARM_SMCCC if ARM64
+	select CMD_ARMFFA
 	select LIB_UUID
 	select ARM_FFA_TRANSPORT_HELPERS
 	help
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v2 3/6] arm_ffa: introduce the FF-A Sandbox driver
  2022-04-15 12:27                   ` [PATCH v2 " abdellatif.elkhlifi
  2022-04-15 12:27                     ` [PATCH v2 1/6] arm_ffa: introduce Arm FF-A low-level driver abdellatif.elkhlifi
  2022-04-15 12:27                     ` [PATCH v2 2/6] arm_ffa: introduce armffa command abdellatif.elkhlifi
@ 2022-04-15 12:28                     ` abdellatif.elkhlifi
  2022-04-15 12:28                     ` [PATCH v2 4/6] arm_ffa: introduce Sandbox test cases for UCLASS_FFA abdellatif.elkhlifi
                                       ` (3 subsequent siblings)
  6 siblings, 0 replies; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-04-15 12:28 UTC (permalink / raw)
  To: u-boot
  Cc: sudeep.holla, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	robh, sjg, trini, vishnu.banavath, xueliang.zhong, nd

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

Provide a Sandbox driver to emulate the FF-A ABIs

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

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

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

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


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v2 4/6] arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  2022-04-15 12:27                   ` [PATCH v2 " abdellatif.elkhlifi
                                       ` (2 preceding siblings ...)
  2022-04-15 12:28                     ` [PATCH v2 3/6] arm_ffa: introduce the FF-A Sandbox driver abdellatif.elkhlifi
@ 2022-04-15 12:28                     ` abdellatif.elkhlifi
  2022-04-15 12:28                     ` [PATCH v2 5/6] arm_ffa: introduce armffa command Sandbox test abdellatif.elkhlifi
                                       ` (2 subsequent siblings)
  6 siblings, 0 replies; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-04-15 12:28 UTC (permalink / raw)
  To: u-boot
  Cc: sudeep.holla, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	robh, sjg, trini, vishnu.banavath, xueliang.zhong, nd

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

Add functional test cases for the FF-A core driver

These tests rely on the FF-A Sandbox driver which helps in
 inspecting the FF-A core driver.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
---
 MAINTAINERS      |   2 +
 test/dm/Makefile |   1 +
 test/dm/ffa.c    | 418 +++++++++++++++++++++++++++++++++++++++++++++++
 test/dm/ffa.h    |  22 +++
 4 files changed, 443 insertions(+)
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/dm/ffa.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 7c439ed1fd..74b7ed9388 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -242,6 +242,8 @@ F:	include/arm_ffa_helper.h
 F:	include/sandbox_arm_ffa.h
 F:	include/sandbox_arm_ffa_helper.h
 F:	lib/arm-ffa/
+F:	test/dm/ffa.c
+F:	test/dm/ffa.h
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/test/dm/Makefile b/test/dm/Makefile
index d46552fbf3..48eab1b1ff 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_SANDBOX_FFA) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..85b71bd808
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,418 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <dm.h>
+#include <dm/test.h>
+#include "ffa.h"
+#include <test/test.h>
+#include <test/ut.h>
+#include <sandbox_arm_ffa_helper.h>
+#include <string.h>
+
+/* Functional tests for the UCLASS_FFA */
+
+static int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
+{
+	char cmd[LOG_CMD_SZ] = {0};
+
+	console_record_reset();
+
+	snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
+	run_command(cmd, 0);
+
+	ut_assert_console_end();
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_fwk_version(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (prvdata->fwk_version != SANDBOX_FWK_VERSION) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: prvdata->fwk_version = 0x%x", __func__,
+			 prvdata->fwk_version);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_endpoint_id(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (prvdata->id) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: prvdata->id = 0x%x", __func__, prvdata->id);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_dev(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->dev) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: device = 0x%p", __func__, prvdata->dev);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_rxtxbuf(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->pair.rxbuf && prvdata->pair.txbuf) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = 0x%llx txbuf = 0x%llx", __func__,
+			 prvdata->pair.rxbuf,
+			 prvdata->pair.txbuf);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_features(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	u32 desc_idx;
+	char msg[LOG_MSG_SZ] = {0};
+
+	snprintf(msg,
+		 LOG_MSG_SZ,
+		 "[%s]: Error: FFA_RXTX_MAP features not found",
+		 __func__);
+
+	for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
+		if (prvdata->features[desc_idx].func_id == FFA_RXTX_MAP) {
+			if (prvdata->features[desc_idx].field1 != RXTX_4K &&
+			    prvdata->features[desc_idx].field1 != RXTX_16K &&
+			    prvdata->features[desc_idx].field1 != RXTX_64K) {
+				snprintf(msg,
+					 LOG_MSG_SZ,
+					 "[%s]: Error: FFA_RXTX_MAP features = 0x%x",
+					 __func__,
+					 prvdata->features[desc_idx].field1);
+					break;
+			}
+			return CMD_RET_SUCCESS;
+		}
+
+	dm_test_ffa_log(uts, msg);
+	return CMD_RET_FAILURE;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+	{
+		if (rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	case FFA_RXTX_UNMAP:
+	{
+		if (!rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	default:
+		return CMD_RET_FAILURE;
+	}
+
+	snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__,
+		 (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP"));
+	dm_test_ffa_log(uts, msg);
+
+	return CMD_RET_FAILURE;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	if (rxbuf_owned) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_interface_data func_data = {0};
+	struct ffa_send_direct_data msg = {0};
+	u32 pattern = 0xaabbccdd;
+	u8 cnt;
+
+	/*
+	 * telling the driver which partition to use
+	 */
+	func_data.data0_size = sizeof(part_id);
+	func_data.data0 = &part_id;
+
+	/*
+	 * filling the message data
+	 */
+	msg.a3 = pattern;
+	msg.a4 = pattern;
+	msg.a5 = pattern;
+	msg.a6 = pattern;
+	msg.a7 = pattern;
+	func_data.data1_size = sizeof(msg);
+	func_data.data1 = &msg;
+
+	ut_assertok(ffa_helper_msg_send_direct_req(&func_data));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u32); cnt++)
+		ut_assertok(((u32 *)&msg)[cnt] != 0xffffffff);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int test_partitions_and_comms(union ffa_partition_uuid *service_uuid,
+				     struct sandbox_ffa_prvdata *sdx_prvdata,
+				     struct unit_test_state *uts)
+{
+	struct ffa_interface_data func_data = {0};
+	u32 count = 0;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx, exp_info_idx;
+	int ret;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	func_data.data0_size = sizeof(*service_uuid);
+	func_data.data0 = service_uuid;
+	func_data.data1_size = sizeof(count);
+	func_data.data1 = &count;
+
+	ut_assertok(ffa_helper_get_partitions_info(&func_data));
+
+	/* make sure partitions are detected */
+	ut_assertok(!count);
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	ut_assertok(!parts_info);
+
+	func_data.data1_size = count * sizeof(struct ffa_partition_info);
+	func_data.data1 = parts_info;
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+	ret = ffa_helper_get_partitions_info(&func_data);
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		free(parts_info);
+		ut_assertok(ret != FFA_ERR_STAT_SUCCESS);
+	}
+
+	/*
+	 * SPs found , verify the partitions information
+	 */
+
+	ret = CMD_RET_FAILURE;
+
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		for (exp_info_idx = 0;
+		     exp_info_idx < sdx_prvdata->partitions.count;
+		     exp_info_idx++) {
+			if (parts_info[info_idx].id ==
+			   sdx_prvdata->partitions.descs[exp_info_idx].info.id) {
+				ret = memcmp(&parts_info[info_idx],
+					     &sdx_prvdata->partitions.descs[exp_info_idx]
+					     .info,
+					     sizeof(struct ffa_partition_info));
+				if (ret)
+					free(parts_info);
+				ut_assertok(ret != 0);
+				/* send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
+			}
+			ret = CMD_RET_SUCCESS;
+		}
+	}
+
+	free(parts_info);
+
+	/* Verify  expected partitions found in the emulated secure world*/
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+	struct ffa_interface_data func_data = {0};
+	u8 rxbuf_flag = 0;
+	union ffa_partition_uuid svc1_uuid = { .bytes = {SANDBOX_SERVICE1_UUID_DATA}};
+	union ffa_partition_uuid svc2_uuid = { .bytes = {SANDBOX_SERVICE2_UUID_DATA}};
+	int ret;
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+
+	ut_assertok(sandbox_ffa_helper_query_core_state(FFA_VERSION, &func_data));
+
+	/* clear private data before the new test */
+	memset(prvdata, 0, sizeof(struct ffa_prvdata));
+	memset(sdx_prvdata, 0, sizeof(struct sandbox_ffa_prvdata));
+
+	/*  test probing FF-A devices */
+	ut_assertok(ffa_helper_bus_discover());
+	ut_assertok(check_dev(prvdata, uts));
+
+	/* test FFA_VERSION */
+	ut_assertok(check_fwk_version(prvdata, uts));
+
+	/* test FFA_ID_GET */
+	ut_assertok(check_endpoint_id(prvdata, uts));
+
+	/* test FFA_FEATURES */
+	ut_assertok(check_features(prvdata, uts));
+
+	/*  test core RX/TX buffers */
+	ut_assertok(check_rxtxbuf(prvdata, uts));
+
+	/* test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	ut_assertok(sandbox_ffa_helper_query_core_state(FFA_RXTX_MAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(&svc1_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_helper_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(&svc2_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_helper_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* test FFA_RXTX_UNMAP */
+	ut_assertok(ffa_helper_unmap_rxtx_buffers());
+
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_helper_query_core_state(FFA_RXTX_UNMAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+
+	struct ffa_interface_data func_data = {0};
+	union ffa_partition_uuid valid_svc_uuid = { .bytes = {SANDBOX_SERVICE1_UUID_DATA}};
+	union ffa_partition_uuid unvalid_svc_uuid = { .bytes = {SANDBOX_SERVICE3_UUID_DATA}};
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	u32 count = 0;
+	u16 part_id = 0;
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+	ut_assertok(sandbox_ffa_helper_query_core_state(FFA_VERSION, &func_data));
+
+	/* clear private data before the new test */
+	memset(prvdata, 0, sizeof(struct ffa_prvdata));
+	memset(sdx_prvdata, 0, sizeof(struct sandbox_ffa_prvdata));
+
+	/* get partitions info before probing the core driver */
+	func_data.data0_size = sizeof(union ffa_partition_uuid);
+	func_data.data0 = &unvalid_svc_uuid;
+	func_data.data1_size = sizeof(count);
+	func_data.data1 = &count;
+
+	ret = ffa_helper_get_partitions_info(&func_data);
+	ut_assertok(ret != -ENODEV);
+
+	/*  probing FF-A devices */
+	ut_assertok(ffa_helper_bus_discover());
+	ut_assertok(check_dev(prvdata, uts));
+
+	/* query partition info using  invalid arguments  */
+	func_data.data0_size = 0;
+	ret = ffa_helper_get_partitions_info(&func_data);
+	ut_assertok(ret != -EINVAL);
+
+	/* query partition info using an invalid UUID  */
+	func_data.data0_size = sizeof(union ffa_partition_uuid);
+	func_data.data0 = &unvalid_svc_uuid;
+	func_data.data1_size = sizeof(count);
+	func_data.data1 = &count;
+
+	ret = ffa_helper_get_partitions_info(&func_data);
+	ut_assertok(ret != -EPERM);
+
+	/* query partition info using a valid UUID  */
+	func_data.data0 = &valid_svc_uuid;
+	count = 0;
+	ret = ffa_helper_get_partitions_info(&func_data);
+	/* make sure partitions are detected */
+	ut_assertok(ret != FFA_ERR_STAT_SUCCESS);
+	ut_assertok(!count);
+
+	/* send data to an invalid partition */
+	func_data.data0_size = sizeof(part_id);
+	func_data.data0 = &part_id;
+	func_data.data1_size = sizeof(msg);
+	func_data.data1 = &msg;
+
+	ret = ffa_helper_msg_send_direct_req(&func_data);
+	ut_assertok(ret != -EPERM);
+
+	/* send data to a valid partition */
+	part_id = ffa_priv_data.partitions.descs[0].info.id;
+	ret = ffa_helper_msg_send_direct_req(&func_data);
+	ut_assertok(ret != FFA_ERR_STAT_SUCCESS);
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
diff --git a/test/dm/ffa.h b/test/dm/ffa.h
new file mode 100644
index 0000000000..11c7980fcf
--- /dev/null
+++ b/test/dm/ffa.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __TEST_DM_FFA_H
+#define __TEST_DM_FFA_H
+
+#define SANDBOX_FWK_VERSION (0x10000)
+
+#define LOG_MSG_SZ (100)
+#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
+
+/* service 3  UUID binary data (little-endian format) */
+#define SANDBOX_SERVICE3_UUID_DATA	\
+	0xfd, 0x42, 0xd5, 0x33,	\
+	0x19, 0xa6, 0x42, 0x09,	\
+	0x9c, 0xc1, 0x2d, 0x72,	\
+	0xcd, 0xd9, 0x98, 0x89
+
+#endif /*__TEST_DM_FFA_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v2 5/6] arm_ffa: introduce armffa command Sandbox test
  2022-04-15 12:27                   ` [PATCH v2 " abdellatif.elkhlifi
                                       ` (3 preceding siblings ...)
  2022-04-15 12:28                     ` [PATCH v2 4/6] arm_ffa: introduce Sandbox test cases for UCLASS_FFA abdellatif.elkhlifi
@ 2022-04-15 12:28                     ` abdellatif.elkhlifi
  2022-04-15 12:28                     ` [PATCH v2 6/6] arm_ffa: introduce FF-A MM communication abdellatif.elkhlifi
  2022-04-15 15:43                     ` [PATCH v2 0/6] introduce Arm FF-A support Tom Rini
  6 siblings, 0 replies; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-04-15 12:28 UTC (permalink / raw)
  To: u-boot
  Cc: sudeep.holla, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	robh, sjg, trini, vishnu.banavath, xueliang.zhong, nd

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

Add Sandbox test for the armffa command

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
---
 MAINTAINERS       |  2 ++
 test/cmd/Makefile |  1 +
 test/cmd/armffa.c | 33 +++++++++++++++++++++++++++++++++
 test/cmd/armffa.h | 13 +++++++++++++
 4 files changed, 49 insertions(+)
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/cmd/armffa.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 74b7ed9388..eb9c3886e6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -242,6 +242,8 @@ F:	include/arm_ffa_helper.h
 F:	include/sandbox_arm_ffa.h
 F:	include/sandbox_arm_ffa_helper.h
 F:	lib/arm-ffa/
+F:	test/cmd/armffa.c
+F:	test/cmd/armffa.h
 F:	test/dm/ffa.c
 F:	test/dm/ffa.h
 
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index a59adb1e6d..d9dc0809d6 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
 obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PWM) += pwm.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_SANDBOX_FFA) += armffa.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..fc41571cf0
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include "armffa.h"
+#include <arm_ffa_helper.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	ut_assertok(ffa_helper_bus_discover());
+
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SE_PROXY_PARTITION_UUID, 0));
+
+	/* armffa ping <ID> */
+	ut_assertok(run_command("armffa ping " SE_PROXY_PARTITION_ID, 0));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
diff --git a/test/cmd/armffa.h b/test/cmd/armffa.h
new file mode 100644
index 0000000000..630dc75e25
--- /dev/null
+++ b/test/cmd/armffa.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __TEST_CMD_FFA_H
+#define __TEST_CMD_FFA_H
+
+#define SE_PROXY_PARTITION_ID "0x1245"
+#define SE_PROXY_PARTITION_UUID "33d532ed-e699-0942-c09c-a798d9cd722d"
+
+#endif /*__TEST_CMD_FFA_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v2 6/6] arm_ffa: introduce FF-A MM communication
  2022-04-15 12:27                   ` [PATCH v2 " abdellatif.elkhlifi
                                       ` (4 preceding siblings ...)
  2022-04-15 12:28                     ` [PATCH v2 5/6] arm_ffa: introduce armffa command Sandbox test abdellatif.elkhlifi
@ 2022-04-15 12:28                     ` abdellatif.elkhlifi
  2022-04-15 15:43                     ` [PATCH v2 0/6] introduce Arm FF-A support Tom Rini
  6 siblings, 0 replies; 478+ messages in thread
From: abdellatif.elkhlifi @ 2022-04-15 12:28 UTC (permalink / raw)
  To: u-boot
  Cc: sudeep.holla, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	robh, sjg, trini, vishnu.banavath, xueliang.zhong, nd,
	Gowtham Suresh Kumar

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

Add MM communication support using FF-A transport

FF-A MM communication allows exchanging data with StandAlonneMM
or smm-gateway secure partitions which run in OP-TEE.

An MM shared buffer and a door bell event are used to exchange
this data.

The data is used by EFI services such as GetVariable()/SetVariable()
 and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
 MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
 buffer with the response data.

The response data is copied back to the communication buffer and
 consumed by the EFI subsystem.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
---
 arch/arm/cpu/armv8/cache.S        |  16 ++
 arch/arm/cpu/armv8/cache_v8.c     |   3 +-
 include/mm_communication.h        |   4 +-
 lib/efi_loader/Kconfig            |  14 +-
 lib/efi_loader/efi_variable_tee.c | 281 +++++++++++++++++++++++++++++-
 5 files changed, 308 insertions(+), 10 deletions(-)

diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S
index d1cee23437..bdbe89e0c5 100644
--- a/arch/arm/cpu/armv8/cache.S
+++ b/arch/arm/cpu/armv8/cache.S
@@ -21,7 +21,11 @@
  * x1: 0 clean & invalidate, 1 invalidate only
  * x2~x9: clobbered
  */
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_dcache_level, "ax"
+#endif
 ENTRY(__asm_dcache_level)
 	lsl	x12, x0, #1
 	msr	csselr_el1, x12		/* select cache level */
@@ -65,7 +69,11 @@ ENDPROC(__asm_dcache_level)
  *
  * flush or invalidate all data cache by SET/WAY.
  */
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_dcache_all, "ax"
+#endif
 ENTRY(__asm_dcache_all)
 	mov	x1, x0
 	dsb	sy
@@ -109,7 +117,11 @@ ENTRY(__asm_flush_dcache_all)
 ENDPROC(__asm_flush_dcache_all)
 .popsection
 
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_invalidate_dcache_all, "ax"
+#endif
 ENTRY(__asm_invalidate_dcache_all)
 	mov	x0, #0x1
 	b	__asm_dcache_all
@@ -182,7 +194,11 @@ ENTRY(__asm_invalidate_icache_all)
 ENDPROC(__asm_invalidate_icache_all)
 .popsection
 
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_invalidate_l3_dcache, "ax"
+#endif
 WEAK(__asm_invalidate_l3_dcache)
 	mov	x0, #0			/* return status as success */
 	ret
diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index 3de18c7675..187a4497a7 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -9,6 +9,7 @@
 
 #include <common.h>
 #include <cpu_func.h>
+#include <efi_loader.h>
 #include <hang.h>
 #include <log.h>
 #include <asm/cache.h>
@@ -425,7 +426,7 @@ __weak void mmu_setup(void)
 /*
  * Performs a invalidation of the entire data cache at all levels
  */
-void invalidate_dcache_all(void)
+void __efi_runtime invalidate_dcache_all(void)
 {
 	__asm_invalidate_dcache_all();
 	__asm_invalidate_l3_dcache();
diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..bb99190956 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -123,7 +123,7 @@ struct __packed efi_mm_communicate_header {
  *
  * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_HEADER.
  */
-struct smm_variable_communicate_header {
+struct __packed smm_variable_communicate_header {
 	efi_uintn_t  function;
 	efi_status_t ret_status;
 	u8           data[];
@@ -145,7 +145,7 @@ struct smm_variable_communicate_header {
  * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
  *
  */
-struct smm_variable_access {
+struct __packed smm_variable_access {
 	efi_guid_t  guid;
 	efi_uintn_t data_size;
 	efi_uintn_t name_size;
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 28657f50c9..0d69133595 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	depends on OPTEE || ARM_FFA_TRANSPORT
 	help
+	  The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver, StandAlonneMM and smm-gateway are supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running under Optee in the trusted world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
 endchoice
 
 config EFI_VARIABLES_PRESEED
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..915ccdafc2 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -15,6 +15,40 @@
 #include <malloc.h>
 #include <mm_communication.h>
 
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+#include <arm_ffa_helper.h>
+#include <cpu_func.h>
+#include <mapmem.h>
+
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+#warning "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_SIZE 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+#warning "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_ADDR 0
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+
+#define ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64 (0xC4000061)
+#define ARM_SVC_ID_SP_EVENT_COMPLETE ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64
+
+#ifndef MM_SP_UUID_DATA
+#warning "MM_SP_UUID_DATA must be defined in include/configs/<board>.h"
+#define MM_SP_UUID_DATA        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+#endif
+
+/* MM_SP_UUID_DATA defined by the platform */
+union ffa_partition_uuid mm_sp_svc_uuid = {.bytes = {MM_SP_UUID_DATA}};
+
+static __efi_runtime_data u16 mm_sp_id;
+
+#endif
+
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -24,6 +58,7 @@ struct mm_connection {
 	u32 session;
 };
 
+#if (IS_ENABLED(CONFIG_OPTEE))
 /**
  * get_connection() - Retrieve OP-TEE session for a specific UUID.
  *
@@ -143,16 +178,238 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 
 	return ret;
 }
+#endif
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+/**
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notifies the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int __efi_runtime ffa_notify_mm_sp(void)
+{
+	struct ffa_interface_data func_data = {0};
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	u32 sp_event_complete;
+	int sp_event_ret;
+
+	func_data.data0_size = sizeof(mm_sp_id);
+	func_data.data0 = &mm_sp_id;
+
+	msg.a3 = FFA_SHARED_MM_BUFFER_ADDR;
+	msg.a4 = FFA_SHARED_MM_BUFFER_SIZE;
+	func_data.data1_size = sizeof(msg);
+	func_data.data1 = &msg;
+
+	ret = ffa_helper_msg_send_direct_req(&func_data);
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	sp_event_complete = msg.a3;
+	sp_event_ret = (int)msg.a4;
+
+	if (sp_event_complete == ARM_SVC_ID_SP_EVENT_COMPLETE && sp_event_ret == MM_SUCCESS)
+		return 0;
+
+	/*
+	 * Failure to notify the MM SP
+	 */
+
+	return -EACCES;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	struct ffa_interface_data func_data = {0};
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	func_data.data0_size = sizeof(mm_sp_svc_uuid);
+	func_data.data0 = &mm_sp_svc_uuid;
+	func_data.data1_size = sizeof(count);
+	func_data.data1 = &count;
+
+	ret = ffa_helper_get_partitions_info(&func_data);
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
+		return ret;
+	}
+
+	if (!count) {
+		log_info("EFI: No MM partition found\n");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
+
+	func_data.data1_size = count *
+		sizeof(struct ffa_partition_info);
+	func_data.data1 = parts_info;
+
+	/*
+	 * ask the driver to fill the
+	 * buffer with the SPs info
+	 */
+	ret = ffa_helper_get_partitions_info(&func_data);
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * MM SPs found , use the first one
+	 */
+
+	mm_sp_id = parts_info[0].id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	free(parts_info);
+
+	return 0;
+}
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t __efi_runtime ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()  != FFA_ERR_STAT_SUCCESS) {
+		log_err("EFI: Failure to discover MM partition ID at boot time\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	efi_memcpy_runtime(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world has cache disabled for device region which we use for shared buffer.
+	 * So, the secure world reads the data from DRAM. Let's flush the cache so the DRAM is
+	 * updated with the latest data.
+	 */
+	#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+	#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+	if (ffa_ret)
+		unmap_sysmem(virt_shared_buf);
+
+	switch (ffa_ret) {
+	case 0:
+	{
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_memcpy_runtime(comm_buf, virt_shared_buf, comm_buf_size);
+			unmap_sysmem(virt_shared_buf);
+			return EFI_BUFFER_TOO_SMALL;
+		}
+
+		efi_memcpy_runtime(comm_buf, virt_shared_buf, rx_data_size);
+		unmap_sysmem(virt_shared_buf);
+
+		return EFI_SUCCESS;
+	}
+	case -EINVAL:
+		return EFI_DEVICE_ERROR;
+	case -EPERM:
+		return EFI_INVALID_PARAMETER;
+	case -EACCES:
+		return EFI_ACCESS_DENIED;
+	case -EBUSY:
+		return EFI_OUT_OF_RESOURCES;
+	default:
+		return EFI_ACCESS_DENIED;
+	}
+}
+#endif
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, StandAlonneMM and smm-gateway are supported.
+ *
  * Return:		status code
  */
-static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
+static efi_status_t __efi_runtime mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 {
 	efi_status_t ret;
 	struct efi_mm_communicate_header *mm_hdr;
@@ -162,9 +419,16 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
+	#if (IS_ENABLED(CONFIG_OPTEE))
 	ret = optee_mm_communicate(comm_buf, dsize);
+	#elif (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+	ret = ffa_mm_communicate(comm_buf, dsize);
+	#endif
 	if (ret != EFI_SUCCESS) {
-		log_err("%s failed!\n", __func__);
+		/* No need for showing a log here. mm_communicate failure happens
+		 * when getVariable() is called with data size set to 0.
+		 * This is not expected so no log shown.
+		 */
 		return ret;
 	}
 
@@ -258,6 +522,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
 		goto out;
 	}
 	*size = var_payload->size;
+
+	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
+			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
+				MM_VARIABLE_COMMUNICATE_SIZE;
+	#endif
+
 	/*
 	 * There seems to be a bug in EDK2 miscalculating the boundaries and
 	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
@@ -697,7 +968,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v2 0/6] introduce Arm FF-A support
  2022-04-15 12:27                   ` [PATCH v2 " abdellatif.elkhlifi
                                       ` (5 preceding siblings ...)
  2022-04-15 12:28                     ` [PATCH v2 6/6] arm_ffa: introduce FF-A MM communication abdellatif.elkhlifi
@ 2022-04-15 15:43                     ` Tom Rini
  2022-05-09 10:55                       ` Abdellatif El Khlifi
  6 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2022-04-15 15:43 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, sudeep.holla, achin.gupta, ilias.apalodimas, robh, sjg,
	vishnu.banavath, xueliang.zhong, nd

[-- Attachment #1: Type: text/plain, Size: 1443 bytes --]

On Fri, Apr 15, 2022 at 01:27:57PM +0100, abdellatif.elkhlifi@arm.com wrote:

> From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> 
> This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> 
> FF-A support is generic by design and can be used by any Arm platform.
> 
> The features added are as follows:
>     
> 1/ FF-A bus driver
> 2/ armffa command
> 3/ FF-A Sandbox driver
> 4/ FF-A Sandbox test cases
> 5/ FF-A MM communication
> 
> The suggested design considers FF-A as a discoverable bus.
> The Secure World is considered as one entity to communicate with using the FF-A bus.
> FF-A communication is handled by one device and one instance (the bus).
> This FF-A driver takes care of all the interactions between Normal world
> and Secure World.
> 
> The Secure World firmware runs  under TrustZone HW (such as Optee). The same approach was followed in the
> FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> 
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Rob Herring <robh@kernel.org>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Cc: Achin Gupta <achin.gupta@arm.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Vishnu Banavath <vishnu.banavath@arm.com>

I don't see a changelog compared with v1.  Are any of the comments there
addressed?  Thanks.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v2 0/6] introduce Arm FF-A support
  2022-04-15 15:43                     ` [PATCH v2 0/6] introduce Arm FF-A support Tom Rini
@ 2022-05-09 10:55                       ` Abdellatif El Khlifi
  2022-05-12 14:04                         ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-05-09 10:55 UTC (permalink / raw)
  To: Tom Rini
  Cc: u-boot, sudeep.holla, achin.gupta, ilias.apalodimas, robh, sjg,
	vishnu.banavath, xueliang.zhong, nd

On Fri, Apr 15, 2022 at 11:43:25AM -0400, Tom Rini wrote:
> On Fri, Apr 15, 2022 at 01:27:57PM +0100, abdellatif.elkhlifi@arm.com wrote:
> 
> > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > 
> > This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> > 
> > FF-A support is generic by design and can be used by any Arm platform.
> > 
> > The features added are as follows:
> >     
> > 1/ FF-A bus driver
> > 2/ armffa command
> > 3/ FF-A Sandbox driver
> > 4/ FF-A Sandbox test cases
> > 5/ FF-A MM communication
> > 
> > The suggested design considers FF-A as a discoverable bus.
> > The Secure World is considered as one entity to communicate with using the FF-A bus.
> > FF-A communication is handled by one device and one instance (the bus).
> > This FF-A driver takes care of all the interactions between Normal world
> > and Secure World.
> > 
> > The Secure World firmware runs  under TrustZone HW (such as Optee). The same approach was followed in the
> > FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> > 
> > Cc: Tom Rini <trini@konsulko.com>
> > Cc: Rob Herring <robh@kernel.org>
> > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > Cc: Achin Gupta <achin.gupta@arm.com>
> > Cc: Simon Glass <sjg@chromium.org>
> > Cc: Vishnu Banavath <vishnu.banavath@arm.com>
> 
> I don't see a changelog compared with v1.  Are any of the comments there
> addressed?  Thanks.
> 
> -- 
> Tom

Thanks Tom. I'll add a changelog for future versions.

The current Changelog:

Changelog:
===============
v2 (15 Apr 2022)
* Make FF-A bus discoverable (remove device tree support, bind and probe FF-A device using device_bind and device_probe)

v1 (29 Mar 2022)
* FF-A bus driver with device tree support
* armffa command
* FF-A Sandbox driver
* FF-A Sandbox test cases
* FF-A MM communication


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v2 0/6] introduce Arm FF-A support
  2022-05-09 10:55                       ` Abdellatif El Khlifi
@ 2022-05-12 14:04                         ` Abdellatif El Khlifi
  2022-05-12 14:43                           ` Ilias Apalodimas
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-05-12 14:04 UTC (permalink / raw)
  To: Tom Rini
  Cc: u-boot, sudeep.holla, achin.gupta, ilias.apalodimas, robh, sjg,
	vishnu.banavath, xueliang.zhong, nd

On Mon, May 09, 2022 at 11:55:14AM +0100, Abdellatif El Khlifi wrote:
> On Fri, Apr 15, 2022 at 11:43:25AM -0400, Tom Rini wrote:
> > On Fri, Apr 15, 2022 at 01:27:57PM +0100, abdellatif.elkhlifi@arm.com wrote:
> > 
> > > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > 
> > > This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> > > 
> > > FF-A support is generic by design and can be used by any Arm platform.
> > > 
> > > The features added are as follows:
> > >     
> > > 1/ FF-A bus driver
> > > 2/ armffa command
> > > 3/ FF-A Sandbox driver
> > > 4/ FF-A Sandbox test cases
> > > 5/ FF-A MM communication
> > > 
> > > The suggested design considers FF-A as a discoverable bus.
> > > The Secure World is considered as one entity to communicate with using the FF-A bus.
> > > FF-A communication is handled by one device and one instance (the bus).
> > > This FF-A driver takes care of all the interactions between Normal world
> > > and Secure World.
> > > 
> > > The Secure World firmware runs  under TrustZone HW (such as Optee). The same approach was followed in the
> > > FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> > > 
> > > Cc: Tom Rini <trini@konsulko.com>
> > > Cc: Rob Herring <robh@kernel.org>
> > > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > > Cc: Achin Gupta <achin.gupta@arm.com>
> > > Cc: Simon Glass <sjg@chromium.org>
> > > Cc: Vishnu Banavath <vishnu.banavath@arm.com>
> > 
> > I don't see a changelog compared with v1.  Are any of the comments there
> > addressed?  Thanks.
> > 
> > -- 
> > Tom
> 
> Thanks Tom. I'll add a changelog for future versions.
> 
> The current Changelog:
> 
> Changelog:
> ===============
> v2 (15 Apr 2022)
> * Make FF-A bus discoverable (remove device tree support, bind and probe FF-A device using device_bind and device_probe)
> 
> v1 (29 Mar 2022)
> * FF-A bus driver with device tree support
> * armffa command
> * FF-A Sandbox driver
> * FF-A Sandbox test cases
> * FF-A MM communication
>

Hello guys, gentle ping, any feedback about the implementation of FF-A as a discoverable
bus ?

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v2 0/6] introduce Arm FF-A support
  2022-05-12 14:04                         ` Abdellatif El Khlifi
@ 2022-05-12 14:43                           ` Ilias Apalodimas
  2022-08-01 17:20                             ` [PATCH v3 0/4] " Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2022-05-12 14:43 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Tom Rini, u-boot, sudeep.holla, achin.gupta, robh, sjg,
	vishnu.banavath, xueliang.zhong, nd

Hi Abdellatif,

On Thu, May 12, 2022 at 03:04:38PM +0100, Abdellatif El Khlifi wrote:
> On Mon, May 09, 2022 at 11:55:14AM +0100, Abdellatif El Khlifi wrote:
> > On Fri, Apr 15, 2022 at 11:43:25AM -0400, Tom Rini wrote:
> > > On Fri, Apr 15, 2022 at 01:27:57PM +0100, abdellatif.elkhlifi@arm.com wrote:
> > > 
> > > > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > 
> > > > This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> > > > 
> > > > FF-A support is generic by design and can be used by any Arm platform.
> > > > 
> > > > The features added are as follows:
> > > >     
> > > > 1/ FF-A bus driver
> > > > 2/ armffa command
> > > > 3/ FF-A Sandbox driver
> > > > 4/ FF-A Sandbox test cases
> > > > 5/ FF-A MM communication
> > > > 
> > > > The suggested design considers FF-A as a discoverable bus.
> > > > The Secure World is considered as one entity to communicate with using the FF-A bus.
> > > > FF-A communication is handled by one device and one instance (the bus).
> > > > This FF-A driver takes care of all the interactions between Normal world
> > > > and Secure World.
> > > > 
> > > > The Secure World firmware runs  under TrustZone HW (such as Optee). The same approach was followed in the
> > > > FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> > > > 
> > > > Cc: Tom Rini <trini@konsulko.com>
> > > > Cc: Rob Herring <robh@kernel.org>
> > > > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > > > Cc: Achin Gupta <achin.gupta@arm.com>
> > > > Cc: Simon Glass <sjg@chromium.org>
> > > > Cc: Vishnu Banavath <vishnu.banavath@arm.com>
> > > 
> > > I don't see a changelog compared with v1.  Are any of the comments there
> > > addressed?  Thanks.
> > > 
> > > -- 
> > > Tom
> > 
> > Thanks Tom. I'll add a changelog for future versions.
> > 
> > The current Changelog:
> > 
> > Changelog:
> > ===============
> > v2 (15 Apr 2022)
> > * Make FF-A bus discoverable (remove device tree support, bind and probe FF-A device using device_bind and device_probe)
> > 
> > v1 (29 Mar 2022)
> > * FF-A bus driver with device tree support
> > * armffa command
> > * FF-A Sandbox driver
> > * FF-A Sandbox test cases
> > * FF-A MM communication
> >
> 
> Hello guys, gentle ping, any feedback about the implementation of FF-A as a discoverable
> bus ?

Apologies for the late reply, I was on vacation.  I'll try having a closer
look on patch #1-5 in the upcoming days.  Can you take a look at my
comments on patch #6 and reply?

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v2 1/6] arm_ffa: introduce Arm FF-A low-level driver
  2022-04-15 12:27                     ` [PATCH v2 1/6] arm_ffa: introduce Arm FF-A low-level driver abdellatif.elkhlifi
@ 2022-05-13 14:23                       ` Ilias Apalodimas
  2022-09-26 10:42                         ` Abdellatif El Khlifi
  2022-05-13 14:40                       ` Jens Wiklander
  1 sibling, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2022-05-13 14:23 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, sudeep.holla, achin.gupta, robh, sjg, trini,
	vishnu.banavath, xueliang.zhong, nd

Hi Abdellatif
On Fri, Apr 15, 2022 at 01:27:58PM +0100, abdellatif.elkhlifi@arm.com wrote:
> From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> 
> Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
> 
> The Firmware Framework for Arm A-profile processors (FF-A)
> describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World leveraging TrustZone
> technology. This driver uses SMC32 calling convention.
> 
> In u-boot FF-A design, FF-A is considered as a discoverable bus.
> The Secure World is considered as one entity to communicate with
> using the FF-A bus. FF-A communication is handled by one device and
> one instance (the bus). This FF-A driver takes care of all the
> interactions between Normal world and Secure World.
> 
> The driver provides helper FF-A interfaces for user layers.
> These helper functions allow clients to pass data and select the
> FF-A function to use for the communication with secure world.
> 
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +++ b/arch/arm/cpu/armv8/smccc-call.S
> @@ -1,6 +1,8 @@
>  /* SPDX-License-Identifier: GPL-2.0 */
>  /*
>   * Copyright (c) 2015, Linaro Limited
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  #include <linux/linkage.h>
>  #include <linux/arm-smccc.h>
> @@ -45,3 +47,28 @@ ENDPROC(__arm_smccc_smc)
>  ENTRY(__arm_smccc_hvc)
>  	SMCCC	hvc
>  ENDPROC(__arm_smccc_hvc)
> +
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +
> +	.macro FFASMCCC instr
> +	.cfi_startproc
> +	\instr	#0
> +	ldr	x9, [sp]
> +	stp	x0, x1, [x9, #ARM_SMCCC_RES_X0_OFFS]
> +	stp	x2, x3, [x9, #ARM_SMCCC_RES_X2_OFFS]
> +	stp	x4, x5, [x9, #ARM_SMCCC_RES_X4_OFFS]
> +	stp	x6, x7, [x9, #ARM_SMCCC_RES_X6_OFFS]
> +	ret
> +	.cfi_endproc
> +	.endm
> +
> +/*
> + * void arm_ffa_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
> + *		  unsigned long a3, unsigned long a4, unsigned long a5,
> + *		  unsigned long a6, unsigned long a7, struct arm_smccc_res *res)
> + */
> +ENTRY(__arm_ffa_smccc_smc)
> +	FFASMCCC	smc
> +ENDPROC(__arm_ffa_smccc_smc)
> +
> +#endif
> diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
> index 22fd541f9a..02a4a42fe6 100644
> --- a/arch/arm/lib/asm-offsets.c
> +++ b/arch/arm/lib/asm-offsets.c
> @@ -9,6 +9,8 @@
>   * generate asm statements containing #defines,
>   * compile this file to assembler, and then extract the
>   * #defines from the assembly-language output.
> + *
> + * (C) Copyright 2022 ARM Limited
>   */
>  
>  #include <common.h>
> @@ -115,6 +117,10 @@ int main(void)
>  #ifdef CONFIG_ARM_SMCCC
>  	DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
>  	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +	DEFINE(ARM_SMCCC_RES_X4_OFFS, offsetof(struct arm_smccc_res, a4));
> +	DEFINE(ARM_SMCCC_RES_X6_OFFS, offsetof(struct arm_smccc_res, a6));
> +#endif
>  	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
>  	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
>  #endif
> diff --git a/common/board_r.c b/common/board_r.c
> index b92c1bb0be..bb5f1d0aa6 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -62,6 +62,10 @@
>  #include <asm-generic/gpio.h>
>  #include <efi_loader.h>
>  
> +#ifdef CONFIG_ARM_FFA_TRANSPORT
> +#include <arm_ffa_helper.h>
> +#endif
> +
>  DECLARE_GLOBAL_DATA_PTR;
>  
>  ulong monitor_flash_len;
> @@ -771,6 +775,9 @@ static init_fnc_t init_sequence_r[] = {
>  	INIT_FUNC_WATCHDOG_RESET
>  	initr_net,
>  #endif
> +#ifdef CONFIG_ARM_FFA_TRANSPORT
> +	ffa_helper_bus_discover,
> +#endif
>  #ifdef CONFIG_POST
>  	initr_post,
>  #endif
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index b26ca8cf70..e83c23789d 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
>  
>  source "drivers/adc/Kconfig"
>  
> +source "drivers/arm-ffa/Kconfig"
> +
>  source "drivers/ata/Kconfig"
>  
>  source "drivers/axi/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 4e7cf28440..6671d2a604 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -107,6 +107,7 @@ obj-y += iommu/
>  obj-y += smem/
>  obj-y += thermal/
>  obj-$(CONFIG_TEE) += tee/
> +obj-$(CONFIG_ARM_FFA_TRANSPORT) += arm-ffa/
>  obj-y += axi/
>  obj-y += ufs/
>  obj-$(CONFIG_W1) += w1/
> diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
> new file mode 100644
> index 0000000000..23815534c4
> --- /dev/null
> +++ b/drivers/arm-ffa/Kconfig
> @@ -0,0 +1,27 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +config ARM_FFA_TRANSPORT
> +	bool "Enable Arm Firmware Framework for Armv8-A driver"
> +	depends on DM && ARM64
> +	select ARM_SMCCC if ARM64
> +	select LIB_UUID
> +	select ARM_FFA_TRANSPORT_HELPERS
> +	help
> +	  The Firmware Framework for Arm A-profile processors (FF-A)
> +	  describes interfaces (ABIs) that standardize communication
> +	  between the Secure World and Normal World leveraging TrustZone
> +	  technology.
> +
> +	  This driver is based on FF-A specification v1.0 and uses SMC32
> +	  calling convention.
> +
> +	  FF-A specification:
> +
> +	  https://developer.arm.com/documentation/den0077/a/?lang=en
> +
> +	  In u-boot FF-A design, FF-A is considered as a discoverable bus.
> +	  The Secure World is considered as one entity to communicate with
> +	  using the FF-A bus.
> +	  FF-A communication is handled by one device and one instance (the bus).
> +	  This FF-A driver takes care of all the interactions between Normal world
> +	  and Secure World.
> diff --git a/drivers/arm-ffa/Makefile b/drivers/arm-ffa/Makefile
> new file mode 100644
> index 0000000000..7bc9a336a9
> --- /dev/null
> +++ b/drivers/arm-ffa/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +#
> +
> +obj-y += arm-ffa-uclass.o core.o
> diff --git a/drivers/arm-ffa/arm-ffa-uclass.c b/drivers/arm-ffa/arm-ffa-uclass.c
> new file mode 100644
> index 0000000000..2439f87586
> --- /dev/null
> +++ b/drivers/arm-ffa/arm-ffa-uclass.c
> @@ -0,0 +1,64 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <arm_ffa.h>
> +#include <errno.h>
> +#include <log.h>
> +#include <asm/global_data.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +UCLASS_DRIVER(ffa) = {
> +	.name		= "ffa",
> +	.id		= UCLASS_FFA,
> +};
> +
> +/**
> + * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher
> + * @func_id:	The FF-A function to be used
> + * @func_data:  Pointer to the FF-A function arguments
> + *				container structure. This also includes
> + *				pointers to the returned data needed by
> + *				clients.
> + *
> + * This runtime function passes the FF-A function ID and its arguments to
> + * the FF-A driver dispatcher.
> + * This function is called by the FF-A helper functions.
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +int __ffa_runtime ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *func_data)
> +{
> +	if (!ffa_device_get_ops()->invoke_func)
> +		return -EINVAL;
> +
> +	return ffa_device_get_ops()->invoke_func(func_id, func_data);
> +}
> +
> +/**
> + * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
> + *
> + * This boot time function makes sure the FF-A bus is discoverable.
> + * Then, the arm_ffa device is probed and ready to use.
> + * This function is called automatically at initcalls
> + * level (after u-boot relocation).
> + *
> + * Arm FF-A transport is implemented through arm_ffa u-boot device managing the FF-A
> + * communication.
> + * All FF-A clients should use the arm_ffa device to use the FF-A transport.
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +int ffa_bus_discover(void)
> +{
> +	return ffa_get_device();
> +}
> diff --git a/drivers/arm-ffa/arm_ffa_prv.h b/drivers/arm-ffa/arm_ffa_prv.h
> new file mode 100644
> index 0000000000..44f258addb
> --- /dev/null
> +++ b/drivers/arm-ffa/arm_ffa_prv.h
> @@ -0,0 +1,193 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#ifndef __ARM_FFA_PRV_H
> +#define __ARM_FFA_PRV_H
> +
> +#include <arm_ffa.h>
> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
> +#include <dm/read.h>
> +
> +/*
> + * This header is private. It is exclusively used by the FF-A driver
> + */
> +
> +/* FF-A core driver name */
> +#define FFA_DRV_NAME "arm_ffa"
> +
> +/* FF-A driver version definitions */
> +
> +#define MAJOR_VERSION_MASK		GENMASK(30, 16)
> +#define MINOR_VERSION_MASK		GENMASK(15, 0)
> +#define GET_FFA_MAJOR_VERSION(x)		\
> +				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> +#define GET_FFA_MINOR_VERSION(x)		\
> +				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> +#define PACK_VERSION_INFO(major, minor)			\
> +	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
> +	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> +
> +#define FFA_MAJOR_VERSION		(1)
> +#define FFA_MINOR_VERSION		(0)
> +#define FFA_VERSION_1_0		\
> +			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> +
> +/* Endpoint ID mask (u-boot endpoint ID) */
> +
> +#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
> +#define GET_SELF_ENDPOINT_ID(x)		\
> +			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> +
> +#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
> +#define PREP_SELF_ENDPOINT_ID(x)		\
> +			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> +
> +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> +
> +#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
> +#define PREP_PART_ENDPOINT_ID(x)		\
> +			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> +
> +/* The FF-A SMC function prototype definition */
> +
> +typedef void (*invoke_ffa_fn_t)(unsigned long a0, unsigned long a1,
> +			unsigned long a2, unsigned long a3, unsigned long a4,
> +			unsigned long a5, unsigned long a6, unsigned long a7,
> +			struct arm_smccc_res *res);
> +
> +/**
> + * enum ffa_conduit - Arm FF-A conduits supported by the Arm FF-A driver
> + * Currently only SMC32 is supported.
> + */
> +enum ffa_conduit {
> +	FFA_CONDUIT_SMC = 0,
> +};
> +
> +/**
> + * FFA_DECLARE_ARGS - FF-A functions local variables
> + * @a0-a7:	local variables used to set registers x0-x7
> + * @res:	the structure hosting the FF-A function return data
> + *
> + * A helper macro for declaring local variables for the FF-A functions  arguments.
> + * The x0-x7 registers are used to exchange data with the secure world.
> + * But, only the bottom 32-bit of thes registers contains the data.
> + */
> +#define FFA_DECLARE_ARGS \
> +	unsigned long a0 = 0; \
> +	unsigned long a1 = 0; \
> +	unsigned long a2 = 0; \
> +	unsigned long a3 = 0; \
> +	unsigned long a4 = 0; \
> +	unsigned long a5 = 0; \
> +	unsigned long a6 = 0; \
> +	unsigned long a7 = 0; \
> +	struct arm_smccc_res res = {0}
> +
> +/* FF-A error codes */
> +#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_INTERRUPTED				(-5)
> +#define FFA_ERR_STAT_DENIED				(-6)
> +#define FFA_ERR_STAT_RETRY				(-7)
> +#define FFA_ERR_STAT_ABORTED				(-8)
> +
> +/**
> + * struct ffa_features_desc - FF-A functions features
> + * @func_id:	FF-A function
> + * @field1:	features read from register w2
> + * @field2:	features read from register w3
> + *
> + * Data structure describing the features of the  FF-A functions queried by
> + * FFA_FEATURES
> + */
> +struct ffa_features_desc {
> +	u32 func_id;
> +	u32 field1;
> +	u32 field2;
> +};
> +
> +/**
> + * enum ffa_rxtx_buf_sizes - minimum sizes supported
> + * for the RX/TX buffers
> + */
> +enum ffa_rxtx_buf_sizes {
> +	RXTX_4K,
> +	RXTX_64K,
> +	RXTX_16K
> +};
> +
> +/*
> + * Number of the FF-A interfaces features descriptors
> + * currently only FFA_RXTX_MAP descriptor is supported
> + */
> +#define FFA_FEATURE_DESC_CNT (1)
> +
> +/**
> + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> + * @rxbuf:	virtual address of the RX buffer
> + * @txbuf:	virtual address of the TX buffer
> + *
> + * Data structure hosting the virtual addresses of the mapped RX/TX buffers
> + * These addresses are used by the FF-A functions that use the RX/TX buffers
> + */
> +struct ffa_rxtxpair {
> +	u64 rxbuf; /* virtual address */
> +	u64 txbuf; /* virtual address */
> +};
> +
> +/**
> + * struct ffa_partition_desc - the secure partition descriptor
> + * @info:	partition information
> + * @UUID:	UUID
> + *
> + * Each partition has its descriptor containing the partitions information and the UUID
> + */
> +struct ffa_partition_desc {
> +	struct ffa_partition_info info;
> +	union ffa_partition_uuid UUID;
> +};
> +
> +/**
> + * struct ffa_partitions - descriptors for all secure partitions
> + * @count:	The number of partitions descriptors
> + * @descs	The partitions descriptors table
> + *
> + * This data structure contains the partitions descriptors table
> + */
> +struct ffa_partitions {
> +	u32 count;
> +	struct ffa_partition_desc *descs; /* virtual address */
> +};
> +
> +/**
> + * struct 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
> + * @conduit:	The selected conduit
> + * @invoke_ffa_fn:	The function executing the FF-A function
> + * @features:	Table of the FF-A functions having features
> + *
> + * The driver data structure hosting all resident data.
> + */
> +struct ffa_prvdata {
> +	struct udevice *dev;
> +	u32 fwk_version;
> +	u16 id;
> +	struct ffa_partitions partitions;
> +	struct ffa_rxtxpair pair;
> +	enum ffa_conduit conduit;
> +	invoke_ffa_fn_t invoke_ffa_fn;
> +	struct ffa_features_desc features[FFA_FEATURE_DESC_CNT];
> +};
> +
> +#endif
> diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c
> new file mode 100644
> index 0000000000..09e4eb753a
> --- /dev/null
> +++ b/drivers/arm-ffa/core.c
> @@ -0,0 +1,1349 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include "arm_ffa_prv.h"
> +#include <asm/global_data.h>
> +#include <asm/io.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 <log.h>
> +#include <malloc.h>
> +#include <mapmem.h>
> +#include <string.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/**
> + * The device private data structure containing all the resident
> + * data read from secure world
> + */
> +struct ffa_prvdata __ffa_runtime_data ffa_priv_data = {0};
> +
> +/*
> + * Driver functions
> + */
> +
> +/**
> + * ffa_get_device - create, bind and probe the arm_ffa device
> + *
> + * This boot time function makes sure the arm_ffa device is
> + * created, bound to this driver, probed and ready to use.
> + * Arm FF-A transport is implemented through a single u-boot
> + * device managing the FF-A bus (arm_ffa).
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +int ffa_get_device(void)
> +{
> +	int ret;
> +
> +	if (ffa_priv_data.dev)
> +		return FFA_ERR_STAT_SUCCESS;
> +
> +	ret = device_bind(dm_root(),
> +			  DM_DRIVER_GET(arm_ffa),
> +			  FFA_DRV_NAME,
> +			  NULL,
> +			  ofnode_null(),
> +			  &ffa_priv_data.dev);
> +	if (ret) {
> +		ffa_priv_data.dev = NULL;
> +		return ret;
> +	}
> +
> +	/* The FF-A bus discovery succeeds when probing is successful */
> +	ret = device_probe(ffa_priv_data.dev);
> +	if (ret) {
> +		ffa_err("can not probe  the device");
> +		device_unbind(ffa_priv_data.dev);
> +		ffa_priv_data.dev = NULL;
> +		return ret;
> +	}
> +
> +	return FFA_ERR_STAT_SUCCESS;
> +}
> +
> +/**
> + * ffa_get_version - FFA_VERSION handler function
> + *
> + * This is the boot time function that implements FFA_VERSION FF-A function
> + * to get from the secure world the FF-A framework version
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_get_version(void)
> +{
> +	u16 major, minor;
> +
> +	FFA_DECLARE_ARGS;
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	a0 = FFA_VERSION;
> +	a1 = FFA_VERSION_1_0;
> +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> +
> +	if (res.a0 == FFA_ERR_STAT_NOT_SUPPORTED) {
> +		ffa_err("A Firmware Framework implementation does not exist");
> +		return -EOPNOTSUPP;
> +	}
> +
> +	major = GET_FFA_MAJOR_VERSION(res.a0);
> +	minor = GET_FFA_MINOR_VERSION(res.a0);
> +
> +	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> +		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> +
> +	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
> +		ffa_info("Versions are compatible ");
> +
> +		ffa_priv_data.fwk_version = res.a0;
> +
> +		return FFA_ERR_STAT_SUCCESS;
> +	}
> +
> +	ffa_info("Versions are incompatible ");
> +	return -EPROTONOSUPPORT;
> +}
> +
> +/**
> + * ffa_get_endpoint_id - FFA_ID_GET handler function
> + *
> + * This is the boot time function that implements FFA_ID_GET FF-A function
> + * to get from the secure world u-boot endpoint ID
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_get_endpoint_id(void)
> +{
> +	FFA_DECLARE_ARGS;
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	a0 = FFA_ID_GET;
> +
> +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> +
> +	switch (res.a0) {
> +	case FFA_ERROR:
> +	{
> +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
> +			ffa_err("This function is not implemented at this FF-A instance");
> +			return -EOPNOTSUPP;
> +		}
> +
> +		ffa_err("Undefined error code (%d)", ((int)res.a2));
> +		return -EINVAL;
> +	}
> +	case FFA_SUCCESS:
> +	{
> +		ffa_priv_data.id = GET_SELF_ENDPOINT_ID(res.a2);
> +		ffa_info("endpoint ID is %u", ffa_priv_data.id);
> +
> +		return FFA_ERR_STAT_SUCCESS;
> +	}
> +	default:
> +	{
> +		ffa_err("Undefined response function (0x%lx)", res.a0);
> +		return -EINVAL;
> +	}
> +	}
> +}
> +
> +/**
> + * ffa_get_features_desc - returns the features descriptor of the specified
> + *						FF-A function
> + * @func_id:	the FF-A function which the features are to be retrieved
> + *
> + * This is a boot time function that searches the features descriptor of the
> + * specified FF-A function
> + *
> + * Return:
> + *
> + * When found, the address of the features descriptor is returned. Otherwise, NULL.
> + */
> +static struct ffa_features_desc *ffa_get_features_desc(u32 func_id)
> +{
> +	u32 desc_idx;
> +
> +	/*
> +	 * search for the descriptor of the selected FF-A interface
> +	 */
> +	for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
> +		if (ffa_priv_data.features[desc_idx].func_id == func_id)
> +			return &ffa_priv_data.features[desc_idx];
> +
> +	return NULL;
> +}
> +
> +/**
> + * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP
> + *							argument
> + *
> + * This is the boot time function that implements FFA_FEATURES FF-A function
> + * to retrieve the FFA_RXTX_MAP features
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_get_rxtx_map_features(void)
> +{
> +	FFA_DECLARE_ARGS;
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	a0 = FFA_FEATURES;
> +	a1 = FFA_RXTX_MAP;
> +
> +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> +
> +	switch (res.a0) {
> +	case FFA_ERROR:
> +	{
> +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
> +			ffa_err("FFA_RXTX_MAP is not implemented at this FF-A instance");
> +			return -EOPNOTSUPP;
> +		}
> +
> +		ffa_err("Undefined error code (%d)", ((int)res.a2));
> +		return -EINVAL;

This happens quite a few times throughout the code.  Why is -EINVAL used
here instead of -FFA_ERR_STAT_INVALID_PARAMETERS for example?

We should either use FFA_* errors consistently of get rid of those entirely
and stick to standard ones,  but let's not mix and match

> +	}
> +	case FFA_SUCCESS:
> +	{
> +		u32 desc_idx;
> +
> +		/*
> +		 * search for an empty descriptor
> +		 */
> +		for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
> +			if (!ffa_priv_data.features[desc_idx].func_id) {
> +				/*
> +				 * populate the descriptor with
> +				 * the interface features data
> +				 */
> +				ffa_priv_data.features[desc_idx].func_id =
> +					FFA_RXTX_MAP;
> +				ffa_priv_data.features[desc_idx].field1 =
> +					res.a2;
> +
> +				ffa_info("FFA_RXTX_MAP features data 0x%lx",
> +					 res.a2);
> +
> +				return FFA_ERR_STAT_SUCCESS;
> +			}
> +
> +		ffa_err("Cannot save FFA_RXTX_MAP features data. Descriptors table full");
> +		return -ENOBUFS;

Similarly -FFA_ERR_STAT_NO_MEMORY or something?

> +	}
> +	default:
> +	{
> +		ffa_err("Undefined response function (0x%lx)",
> +			res.a0);
> +		return -EINVAL;
> +	}
> +	}
> +}
> +
> +/**
> + * ffa_get_rxtx_buffers_pages_cnt - reads from the features data descriptors
> + *						the minimum number of pages in each of the RX/TX
> + *						buffers
> + * @buf_4k_pages: Pointer to the minimum number of pages
> + *
> + * This is the boot time function that  returns the minimum number of pages
> + *  in each of the RX/TX buffers
> + *
> + * Return:
> + *
> + * buf_4k_pages points to the returned number of pages
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_get_rxtx_buffers_pages_cnt(size_t *buf_4k_pages)
> +{
> +	struct ffa_features_desc *desc = NULL;
> +
> +	if (!buf_4k_pages)
> +		return -EINVAL;
> +
> +	desc = ffa_get_features_desc(FFA_RXTX_MAP);
> +	if (!desc)
> +		return -EINVAL;
> +
> +	switch (desc->field1) {
> +	case RXTX_4K:
> +		*buf_4k_pages = 1;
> +		break;
> +	case RXTX_16K:
> +		*buf_4k_pages = 4;
> +		break;
> +	case RXTX_64K:
> +		*buf_4k_pages = 16;
> +		break;
> +	default:
> +		ffa_err("RX/TX buffer size not supported");
> +		return -EINVAL;
> +	}
> +
> +	return FFA_ERR_STAT_SUCCESS;
> +}
> +
> +/**
> + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> + *			  buffers
> + *
> + * This is the boot time function used to free the RX/TX buffers
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_free_rxtx_buffers(size_t buf_4k_pages)
> +{
> +	efi_status_t free_rxbuf_ret, free_txbuf_ret;
> +
> +	ffa_info("Freeing RX/TX buffers");
> +
> +	free_rxbuf_ret = efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
> +	free_txbuf_ret = efi_free_pages(ffa_priv_data.pair.txbuf, buf_4k_pages);
> +
> +	if (free_rxbuf_ret != EFI_SUCCESS || free_txbuf_ret != EFI_SUCCESS) {
> +		ffa_err("Failed to free RX/TX buffers (rx: %lu , tx: %lu)",
> +			free_rxbuf_ret,
> +			free_txbuf_ret);
> +		return -EINVAL;
> +	}
> +
> +	ffa_priv_data.pair.rxbuf = 0;
> +	ffa_priv_data.pair.txbuf = 0;

Should those be set to 0 regardless of the efi_free_pages() outcome? If not
then you probably need to handle those one by one.  As is it right now one
failure to free a buffer means both of those won't be set

> +
> +	return FFA_ERR_STAT_SUCCESS;
> +}
> +
> +/**
> + * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
> + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> + *			  buffers
> + *
> + * This is the boot time function used by ffa_map_rxtx_buffers to allocate
> + * the RX/TX buffers before mapping them
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_alloc_rxtx_buffers(size_t buf_4k_pages)
> +{
> +#if CONFIG_IS_ENABLED(EFI_LOADER)
> +
> +	efi_status_t efi_ret;
> +	void *virt_txbuf;
> +	void *virt_rxbuf;
> +
> +	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
> +		 buf_4k_pages);
> +
> +	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> +				     EFI_BOOT_SERVICES_DATA,
> +				     buf_4k_pages,
> +				     &ffa_priv_data.pair.rxbuf);
> +

Why are we specifically limiting this to EFI?  I understand using efi
allocated memory for potential runtime operations, were we need the memory
preserved, but why here?

There's also a side effect with this allocation.  The EFI subsystem doesn't
usually come up until u-boot is fully up and running.  This call will force 
it to start way earlier

> +	if (efi_ret != EFI_SUCCESS) {
> +		ffa_priv_data.pair.rxbuf = 0;
> +		ffa_err("Failure to allocate RX buffer (EFI error: 0x%lx)",
> +			efi_ret);
> +
> +		return -ENOBUFS;
> +	}
> +
> +	ffa_info("RX buffer at virtual address 0x%llx",
> +		 ffa_priv_data.pair.rxbuf);
> +
> +	virt_rxbuf = (void *)ffa_priv_data.pair.rxbuf;
> +
> +	/*
> +	 * make sure the buffer is clean before use
> +	 */
> +	memset(virt_rxbuf, 0, buf_4k_pages * SZ_4K);
> +
> +	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> +				     EFI_RUNTIME_SERVICES_DATA,
> +				     buf_4k_pages,
> +				     &ffa_priv_data.pair.txbuf);
> +
> +	if (efi_ret != EFI_SUCCESS) {
> +		efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
> +		ffa_priv_data.pair.rxbuf = 0;
> +		ffa_priv_data.pair.txbuf = 0;
> +		ffa_err("Failure to allocate the TX buffer (EFI error: 0x%lx)"
> +			, efi_ret);
> +
> +		return -ENOBUFS;
> +	}
> +
> +	ffa_info("TX buffer at virtual address 0x%llx",
> +		 ffa_priv_data.pair.txbuf);
> +
> +	virt_txbuf = (void *)ffa_priv_data.pair.txbuf;
> +
> +	/*
> +	 * make sure the buffer is clean before use
> +	 */
> +	memset(virt_txbuf, 0, buf_4k_pages * SZ_4K);
> +
> +	return FFA_ERR_STAT_SUCCESS;
> +
> +#else
> +	return -ENOBUFS;
> +#endif
> +}
> +
> +/**
> + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> + *			  buffers
> + *
> + * This is the boot time function that implements FFA_RXTX_MAP FF-A function
> + * to map the RX/TX buffers
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_map_rxtx_buffers(size_t buf_4k_pages)
> +{
> +	int ret;
> +
> +	FFA_DECLARE_ARGS;
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	ret = ffa_alloc_rxtx_buffers(buf_4k_pages);
> +	if (ret != FFA_ERR_STAT_SUCCESS)
> +		return ret;
> +
> +	a0 = FFA_RXTX_MAP;
> +	a1 = ffa_priv_data.pair.txbuf;
> +	a2 = ffa_priv_data.pair.rxbuf;
> +	a3 = buf_4k_pages;
> +
> +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> +
> +	switch (res.a0) {
> +	case FFA_ERROR:
> +	{
> +		switch (((int)res.a2)) {
> +		case FFA_ERR_STAT_INVALID_PARAMETERS:
> +			ffa_err("One or more fields in input parameters is incorrectly encoded");
> +			ret = -EPERM;
> +			break;
> +		case FFA_ERR_STAT_NO_MEMORY:
> +			ffa_err("Not enough memory");
> +			ret = -ENOMEM;
> +			break;
> +		case FFA_ERR_STAT_DENIED:
> +			ffa_err("Buffer pair already registered");
> +			ret = -EACCES;
> +			break;
> +		case FFA_ERR_STAT_NOT_SUPPORTED:
> +			ffa_err("This function is not implemented at this FF-A instance");
> +			ret = -EOPNOTSUPP;
> +			break;
> +		default:
> +			ffa_err("Undefined error (%d)",
> +				((int)res.a2));
> +			ret = -EINVAL;
> +		}

Can we have an array with string literals for the errors and do a
lookup instead of nested case switches?

> +		break;
> +	}
> +	case FFA_SUCCESS:
> +		ffa_info("RX/TX buffers mapped");
> +		return FFA_ERR_STAT_SUCCESS;
> +	default:
> +		ffa_err("Undefined response function (0x%lx)",
> +			res.a0);
> +		ret = -EINVAL;
> +	}
> +
> +	ffa_free_rxtx_buffers(buf_4k_pages);
> +
> +	return ret;
> +}
> +
> +/**
> + * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
> + *
> + * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function
> + * to unmap the RX/TX buffers
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_unmap_rxtx_buffers(void)
> +{
> +	FFA_DECLARE_ARGS;
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	a0 = FFA_RXTX_UNMAP;
> +	a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id);
> +
> +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> +
> +	switch (res.a0) {
> +	case FFA_ERROR:
> +	{
> +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
> +			panic("[FFA] FFA_RXTX_UNMAP is not implemented at this FF-A instance\n");
> +		else if (((int)res.a2) == FFA_ERR_STAT_INVALID_PARAMETERS)
> +			panic("[FFA] There is no buffer pair registered on behalf of the caller\n");
> +		else
> +			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));

There's panics sprinkled around the code.  Are all those cases really
fatal?

> +	}
> +	case FFA_SUCCESS:
> +	{
> +		size_t buf_4k_pages = 0;
> +		int ret;
> +
> +		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
> +		if (ret != FFA_ERR_STAT_SUCCESS)
> +			panic("[FFA] RX/TX buffers unmapped but failure in getting pages count\n");
> +
> +		ret = ffa_free_rxtx_buffers(buf_4k_pages);
> +		if (ret != FFA_ERR_STAT_SUCCESS)
> +			panic("[FFA] RX/TX buffers unmapped but failure in freeing the memory\n");
> +
> +		ffa_info("RX/TX buffers unmapped and memory freed");
> +
> +		return FFA_ERR_STAT_SUCCESS;
> +	}
> +	default:
> +		panic("[FFA] Undefined response function (0x%lx)", res.a0);
> +	}
> +}
> +
> +/**
> + * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
> + *
> + * This is the boot time function that invokes FFA_RX_RELEASE FF-A function
> + * to release the ownership of the RX buffer
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_release_rx_buffer(void)
> +{
> +	FFA_DECLARE_ARGS;
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	a0 = FFA_RX_RELEASE;
> +
> +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> +
> +	switch (res.a0) {
> +	case FFA_ERROR:
> +	{
> +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
> +			panic("[FFA] FFA_RX_RELEASE is not implemented at this FF-A instance\n");
> +		else if (((int)res.a2) == FFA_ERR_STAT_DENIED)
> +			panic("[FFA] Caller did not have ownership of the RX buffer\n");
> +		else
> +			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
> +	}
> +	case FFA_SUCCESS:
> +		return FFA_ERR_STAT_SUCCESS;
> +
> +	default:
> +		panic("[FFA] Undefined response function (0x%lx)\n", res.a0);
> +	}
> +}
> +
> +/**
> + * ffa_uuid_are_identical - checks whether two given UUIDs are identical
> + * @uuid1: first UUID
> + * @uuid2: second UUID
> + *
> + * This is a boot time function used by ffa_read_partitions_info to search
> + * for a UUID in the partitions descriptors table
> + *
> + * Return:
> + *
> + * 1 when UUIDs match. Otherwise, 0
> + */
> +int ffa_uuid_are_identical(const union ffa_partition_uuid *uuid1,
> +			   const union ffa_partition_uuid *uuid2)
> +{
> +	if (!uuid1 || !uuid2)
> +		return 0;
> +
> +	return (!memcmp(uuid1, uuid2, sizeof(union ffa_partition_uuid)));
> +}
> +
> +/**
> + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> + *							and saves it in the private structure
> + * @count: The number of partitions queried
> + * @part_uuid: Pointer to the partition(s) UUID
> + *
> + * This is the boot time function that reads the partitions information
> + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> + * data structure.
> + *
> + * Return:
> + *
> + * The private data structure is updated with the partition(s) information
> + * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
> + */
> +static int ffa_read_partitions_info(u32 count, union ffa_partition_uuid *part_uuid)
> +{
> +	if (!count) {
> +		ffa_err("No partition detected");
> +		return -ENODATA;
> +	}
> +
> +	ffa_info("Reading partitions data from the RX buffer");
> +
> +#if CONFIG_IS_ENABLED(EFI_LOADER)
> +
> +	if (!part_uuid) {
> +		/*
> +		 * querying information of all partitions
> +		 */
> +		u64 data_pages;
> +		u64 data_bytes;
> +		efi_status_t efi_ret;
> +		size_t buf_4k_pages = 0;
> +		u32 desc_idx;
> +		struct ffa_partition_info *parts_info;
> +		int ret;
> +
> +		data_bytes = count * sizeof(struct ffa_partition_desc);
> +		data_pages = efi_size_in_pages(data_bytes);
> +
> +		/*
> +		 * get the RX buffer size in pages
> +		 */
> +		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
> +		if (ret != FFA_ERR_STAT_SUCCESS) {
> +			ffa_err("Can not get the RX buffer size (error %d)", ret);
> +			return ret;
> +		}
> +
> +		if (data_pages > buf_4k_pages) {
> +			ffa_err("Partitions data size exceeds the RX buffer size:");
> +			ffa_err("    Sizes in pages: data %llu , RX buffer %lu ",
> +				data_pages,
> +				buf_4k_pages);
> +
> +			return -ENOMEM;
> +		}
> +
> +		efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> +					     EFI_RUNTIME_SERVICES_DATA,
> +					     data_pages,
> +					     (u64 *)&ffa_priv_data.partitions.descs);
> +

Same questions here.  Why are we using the EFI APIs to allocate buffers?

> +		if (efi_ret != EFI_SUCCESS) {
> +			ffa_priv_data.partitions.descs = NULL;
> +
> +			ffa_err("Cannot  allocate partitions data buffer (EFI error 0x%lx)",
> +				efi_ret);
> +
> +			return -ENOBUFS;
> +		}
> +
> +		/*
> +		 * make sure the buffer is clean before use
> +		 */
> +		memset(ffa_priv_data.partitions.descs, 0,
> +		       data_pages * SZ_4K);
> +
> +		parts_info = (struct ffa_partition_info *)ffa_priv_data.pair.rxbuf;
> +
> +		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
> +			ffa_priv_data.partitions.descs[desc_idx].info =
> +				parts_info[desc_idx];
> +
> +			ffa_info("Partition ID %x : info cached",
> +				 ffa_priv_data.partitions.descs[desc_idx].info.id);
> +		}
> +
> +		ffa_priv_data.partitions.count = count;
> +
> +		ffa_info("%d partition(s) found and cached", count);
> +
> +	} else {
> +		u32 rx_desc_idx, cached_desc_idx;
> +		struct ffa_partition_info *parts_info;
> +		u8 desc_found;
> +
> +		parts_info = (struct ffa_partition_info *)ffa_priv_data.pair.rxbuf;
> +
> +		/*
> +		 * search for the SP IDs read from the RX buffer
> +		 * in the already cached SPs.
> +		 * Update the UUID when ID found.
> +		 */
> +		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
> +			desc_found = 0;
> +
> +			/*
> +			 * search the current ID in the cached partitions
> +			 */
> +			for (cached_desc_idx = 0;
> +			     cached_desc_idx < ffa_priv_data.partitions.count;
> +			     cached_desc_idx++) {
> +				/*
> +				 * save the UUID
> +				 */
> +				if (ffa_priv_data.partitions.descs[cached_desc_idx].info.id ==
> +				    parts_info[rx_desc_idx].id) {
> +					ffa_priv_data.partitions.descs[cached_desc_idx].UUID =
> +						*part_uuid;
> +
> +					desc_found = 1;
> +					break;
> +				}
> +			}
> +
> +			if (!desc_found)
> +				return -ENODATA;
> +		}
> +	}
> +#else
> +#warning "arm_ffa: reading FFA_PARTITION_INFO_GET data not implemented"
> +#endif
> +
> +	return  FFA_ERR_STAT_SUCCESS;
> +}
> +
> +/**
> + * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET
> + *							and saves partitions data
> + * @part_uuid: Pointer to the partition(s) UUID
> + * @pcount: Pointer to the number of partitions variable filled when querying
> + *
> + * This is the boot time function that executes the FFA_PARTITION_INFO_GET
> + * to query the partitions data. Then, it calls ffa_read_partitions_info
> + * to save the data in the private data structure.
> + *
> + * After reading the data the RX buffer is released using ffa_release_rx_buffer
> + *
> + * Return:
> + *
> + * When part_uuid is NULL, all partitions data are retrieved from secure world
> + * When part_uuid is non NULL, data for partitions matching the given UUID are
> + * retrieved and the number of partitions is returned
> + * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
> + */
> +static int ffa_query_partitions_info(union ffa_partition_uuid *part_uuid,
> +				     u32 *pcount)
> +{
> +	unsigned long a0 = 0;
> +	union ffa_partition_uuid query_uuid = {0};
> +	unsigned long a5 = 0;
> +	unsigned long a6 = 0;
> +	unsigned long a7 = 0;
> +	struct arm_smccc_res res = {0};
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	a0 = FFA_PARTITION_INFO_GET;
> +
> +	/*
> +	 * If a UUID is specified. Information for one or more
> +	 * partitions in the system is queried. Otherwise, information
> +	 * for all installed partitions is queried
> +	 */
> +
> +	if (part_uuid) {
> +		if (!pcount)
> +			return -EINVAL;
> +
> +		query_uuid = *part_uuid;
> +	}
> +
> +	ffa_priv_data.invoke_ffa_fn(a0, query_uuid.words.a1, query_uuid.words.a2,
> +				    query_uuid.words.a3, query_uuid.words.a4,
> +				    a5, a6, a7, &res);
> +
> +	switch (res.a0) {
> +	case FFA_ERROR:
> +	{
> +		switch (((int)res.a2)) {
> +		case FFA_ERR_STAT_INVALID_PARAMETERS:
> +			ffa_err("Unrecognized UUID");
> +			return -EPERM;
> +		case FFA_ERR_STAT_NO_MEMORY:
> +			ffa_err("Results cannot fit in RX buffer of the caller");
> +			return -ENOMEM;
> +		case FFA_ERR_STAT_DENIED:
> +			ffa_err("Callee is not in a state to handle this request");
> +			return -EACCES;
> +		case FFA_ERR_STAT_NOT_SUPPORTED:
> +			ffa_err("This function is not implemented at this FF-A instance");
> +			return -EOPNOTSUPP;
> +		case FFA_ERR_STAT_BUSY:
> +			ffa_err("RX buffer of the caller is not free");
> +			return -EBUSY;
> +		default:
> +			ffa_err("Undefined error (%d)", ((int)res.a2));
> +			return -EINVAL;
> +		}
> +	}

Same cases as above. Please map those in an array or something and just do
a lookup to print an error

> +	case FFA_SUCCESS:
> +	{
> +		int ret;
> +
> +		/*
> +		 * res.a2 contains the count of partition information descriptors
> +		 * populated in the RX buffer
> +		 */
> +		if (res.a2) {
> +			ret = ffa_read_partitions_info(res.a2, part_uuid);
> +			if (ret)
> +				ffa_err("Failed to read partition(s) data , error (%d)", ret);
> +		}
> +
> +		/*
> +		 * return the SP count
> +		 */
> +		if (part_uuid) {
> +			if (!ret)
> +				*pcount = res.a2;
> +			else
> +				*pcount = 0;
> +		}

If I am following the code correctly this can be called with (NULL, NULL),
which means that the previous !pcount check won't apply.  Is there any
other check I am missing?

> +		/*
> +		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
> +		 * is assigned to the consumer (u-boot). So, we need to give
> +		 * the ownership back to the secure world
> +		 */
> +		ret = ffa_release_rx_buffer();
> +
> +		if (!part_uuid && !res.a2) {
> +			ffa_err("[FFA] no partition installed in the system");
> +			return -ENODEV;
> +		}
> +
> +		return ret;
> +	}
> +	default:
> +		ffa_err("Undefined response function (0x%lx)", res.a0);
> +		return  -EINVAL;
> +	}
> +}
> +
> +/**
 
[...]

Regards
/Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v2 1/6] arm_ffa: introduce Arm FF-A low-level driver
  2022-04-15 12:27                     ` [PATCH v2 1/6] arm_ffa: introduce Arm FF-A low-level driver abdellatif.elkhlifi
  2022-05-13 14:23                       ` Ilias Apalodimas
@ 2022-05-13 14:40                       ` Jens Wiklander
  2022-09-26 11:30                         ` Abdellatif El Khlifi
  1 sibling, 1 reply; 478+ messages in thread
From: Jens Wiklander @ 2022-05-13 14:40 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, sudeep.holla, achin.gupta, ilias.apalodimas, robh, sjg,
	trini, vishnu.banavath, xueliang.zhong, nd

On Fri, Apr 15, 2022 at 01:27:58PM +0100, abdellatif.elkhlifi@arm.com wrote:
> From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> 
> Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
> 
> The Firmware Framework for Arm A-profile processors (FF-A)
> describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World leveraging TrustZone
> technology. This driver uses SMC32 calling convention.

How come only the SMC32 calling convention is used? What if you need
64-bit pointers for some reason (RXTX_MAP comes to mind) ? Doing the
64-bit calling convention at the same time can't be much more work.

> 
> In u-boot FF-A design, FF-A is considered as a discoverable bus.
> The Secure World is considered as one entity to communicate with
> using the FF-A bus. FF-A communication is handled by one device and
> one instance (the bus). This FF-A driver takes care of all the
> interactions between Normal world and Secure World.
> 
> The driver provides helper FF-A interfaces for user layers.
> These helper functions allow clients to pass data and select the
> FF-A function to use for the communication with secure world.
> 
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> ---
>  MAINTAINERS                      |    8 +
>  arch/arm/cpu/armv8/smccc-call.S  |   27 +
>  arch/arm/lib/asm-offsets.c       |    6 +
>  common/board_r.c                 |    7 +
>  drivers/Kconfig                  |    2 +
>  drivers/Makefile                 |    1 +
>  drivers/arm-ffa/Kconfig          |   27 +
>  drivers/arm-ffa/Makefile         |    6 +
>  drivers/arm-ffa/arm-ffa-uclass.c |   64 ++
>  drivers/arm-ffa/arm_ffa_prv.h    |  193 +++++
>  drivers/arm-ffa/core.c           | 1349 ++++++++++++++++++++++++++++++
>  include/arm_ffa.h                |  190 +++++
>  include/arm_ffa_helper.h         |   45 +
>  include/dm/uclass-id.h           |    1 +
>  include/linux/arm-smccc.h        |   28 +-
>  lib/Kconfig                      |    1 +
>  lib/Makefile                     |    1 +
>  lib/arm-ffa/Kconfig              |    6 +
>  lib/arm-ffa/Makefile             |    8 +
>  lib/arm-ffa/arm_ffa_helper.c     |  188 +++++
>  lib/efi_loader/efi_boottime.c    |   17 +
>  21 files changed, 2174 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/arm-ffa/Kconfig
>  create mode 100644 drivers/arm-ffa/Makefile
>  create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
>  create mode 100644 drivers/arm-ffa/core.c
>  create mode 100644 include/arm_ffa.h
>  create mode 100644 include/arm_ffa_helper.h
>  create mode 100644 lib/arm-ffa/Kconfig
>  create mode 100644 lib/arm-ffa/Makefile
>  create mode 100644 lib/arm-ffa/arm_ffa_helper.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index aca97cd2a3..efa17206b8 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -232,6 +232,14 @@ F:	board/CZ.NIC/
>  F:	configs/turris_*_defconfig
>  F:	include/configs/turris_*.h
>  
> +ARM FF-A
> +M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +S:	Maintained
> +F:	drivers/arm-ffa/
> +F:	include/arm_ffa.h
> +F:	include/arm_ffa_helper.h
> +F:	lib/arm-ffa/
> +
>  ARM FREESCALE IMX
>  M:	Stefano Babic <sbabic@denx.de>
>  M:	Fabio Estevam <festevam@gmail.com>
> diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
> index dc92b28777..9a6aebf194 100644
> --- a/arch/arm/cpu/armv8/smccc-call.S
> +++ b/arch/arm/cpu/armv8/smccc-call.S
> @@ -1,6 +1,8 @@
>  /* SPDX-License-Identifier: GPL-2.0 */
>  /*
>   * Copyright (c) 2015, Linaro Limited
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  #include <linux/linkage.h>
>  #include <linux/arm-smccc.h>
> @@ -45,3 +47,28 @@ ENDPROC(__arm_smccc_smc)
>  ENTRY(__arm_smccc_hvc)
>  	SMCCC	hvc
>  ENDPROC(__arm_smccc_hvc)
> +
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +
> +	.macro FFASMCCC instr
> +	.cfi_startproc
> +	\instr	#0
> +	ldr	x9, [sp]
> +	stp	x0, x1, [x9, #ARM_SMCCC_RES_X0_OFFS]
> +	stp	x2, x3, [x9, #ARM_SMCCC_RES_X2_OFFS]
> +	stp	x4, x5, [x9, #ARM_SMCCC_RES_X4_OFFS]
> +	stp	x6, x7, [x9, #ARM_SMCCC_RES_X6_OFFS]
> +	ret
> +	.cfi_endproc
> +	.endm
> +
> +/*
> + * void arm_ffa_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
> + *		  unsigned long a3, unsigned long a4, unsigned long a5,
> + *		  unsigned long a6, unsigned long a7, struct arm_smccc_res *res)
> + */
> +ENTRY(__arm_ffa_smccc_smc)
> +	FFASMCCC	smc
> +ENDPROC(__arm_ffa_smccc_smc)
> +
> +#endif
> diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
> index 22fd541f9a..02a4a42fe6 100644
> --- a/arch/arm/lib/asm-offsets.c
> +++ b/arch/arm/lib/asm-offsets.c
> @@ -9,6 +9,8 @@
>   * generate asm statements containing #defines,
>   * compile this file to assembler, and then extract the
>   * #defines from the assembly-language output.
> + *
> + * (C) Copyright 2022 ARM Limited
>   */
>  
>  #include <common.h>
> @@ -115,6 +117,10 @@ int main(void)
>  #ifdef CONFIG_ARM_SMCCC
>  	DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
>  	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +	DEFINE(ARM_SMCCC_RES_X4_OFFS, offsetof(struct arm_smccc_res, a4));
> +	DEFINE(ARM_SMCCC_RES_X6_OFFS, offsetof(struct arm_smccc_res, a6));
> +#endif
>  	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
>  	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
>  #endif
> diff --git a/common/board_r.c b/common/board_r.c
> index b92c1bb0be..bb5f1d0aa6 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -62,6 +62,10 @@
>  #include <asm-generic/gpio.h>
>  #include <efi_loader.h>
>  
> +#ifdef CONFIG_ARM_FFA_TRANSPORT
> +#include <arm_ffa_helper.h>
> +#endif
> +
>  DECLARE_GLOBAL_DATA_PTR;
>  
>  ulong monitor_flash_len;
> @@ -771,6 +775,9 @@ static init_fnc_t init_sequence_r[] = {
>  	INIT_FUNC_WATCHDOG_RESET
>  	initr_net,
>  #endif
> +#ifdef CONFIG_ARM_FFA_TRANSPORT
> +	ffa_helper_bus_discover,
> +#endif
>  #ifdef CONFIG_POST
>  	initr_post,
>  #endif
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index b26ca8cf70..e83c23789d 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
>  
>  source "drivers/adc/Kconfig"
>  
> +source "drivers/arm-ffa/Kconfig"
> +
>  source "drivers/ata/Kconfig"
>  
>  source "drivers/axi/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 4e7cf28440..6671d2a604 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -107,6 +107,7 @@ obj-y += iommu/
>  obj-y += smem/
>  obj-y += thermal/
>  obj-$(CONFIG_TEE) += tee/
> +obj-$(CONFIG_ARM_FFA_TRANSPORT) += arm-ffa/
>  obj-y += axi/
>  obj-y += ufs/
>  obj-$(CONFIG_W1) += w1/
> diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
> new file mode 100644
> index 0000000000..23815534c4
> --- /dev/null
> +++ b/drivers/arm-ffa/Kconfig
> @@ -0,0 +1,27 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +config ARM_FFA_TRANSPORT
> +	bool "Enable Arm Firmware Framework for Armv8-A driver"
> +	depends on DM && ARM64
> +	select ARM_SMCCC if ARM64
> +	select LIB_UUID
> +	select ARM_FFA_TRANSPORT_HELPERS
> +	help
> +	  The Firmware Framework for Arm A-profile processors (FF-A)
> +	  describes interfaces (ABIs) that standardize communication
> +	  between the Secure World and Normal World leveraging TrustZone
> +	  technology.
> +
> +	  This driver is based on FF-A specification v1.0 and uses SMC32
> +	  calling convention.
> +
> +	  FF-A specification:
> +
> +	  https://developer.arm.com/documentation/den0077/a/?lang=en
> +
> +	  In u-boot FF-A design, FF-A is considered as a discoverable bus.
> +	  The Secure World is considered as one entity to communicate with
> +	  using the FF-A bus.
> +	  FF-A communication is handled by one device and one instance (the bus).
> +	  This FF-A driver takes care of all the interactions between Normal world
> +	  and Secure World.
> diff --git a/drivers/arm-ffa/Makefile b/drivers/arm-ffa/Makefile
> new file mode 100644
> index 0000000000..7bc9a336a9
> --- /dev/null
> +++ b/drivers/arm-ffa/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +#
> +
> +obj-y += arm-ffa-uclass.o core.o
> diff --git a/drivers/arm-ffa/arm-ffa-uclass.c b/drivers/arm-ffa/arm-ffa-uclass.c
> new file mode 100644
> index 0000000000..2439f87586
> --- /dev/null
> +++ b/drivers/arm-ffa/arm-ffa-uclass.c
> @@ -0,0 +1,64 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <arm_ffa.h>
> +#include <errno.h>
> +#include <log.h>
> +#include <asm/global_data.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +UCLASS_DRIVER(ffa) = {
> +	.name		= "ffa",
> +	.id		= UCLASS_FFA,
> +};
> +
> +/**
> + * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher
> + * @func_id:	The FF-A function to be used
> + * @func_data:  Pointer to the FF-A function arguments
> + *				container structure. This also includes
> + *				pointers to the returned data needed by
> + *				clients.
> + *
> + * This runtime function passes the FF-A function ID and its arguments to
> + * the FF-A driver dispatcher.
> + * This function is called by the FF-A helper functions.
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +int __ffa_runtime ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *func_data)
> +{
> +	if (!ffa_device_get_ops()->invoke_func)
> +		return -EINVAL;
> +
> +	return ffa_device_get_ops()->invoke_func(func_id, func_data);
> +}
> +
> +/**
> + * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
> + *
> + * This boot time function makes sure the FF-A bus is discoverable.
> + * Then, the arm_ffa device is probed and ready to use.
> + * This function is called automatically at initcalls
> + * level (after u-boot relocation).
> + *
> + * Arm FF-A transport is implemented through arm_ffa u-boot device managing the FF-A
> + * communication.
> + * All FF-A clients should use the arm_ffa device to use the FF-A transport.
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +int ffa_bus_discover(void)
> +{
> +	return ffa_get_device();
> +}
> diff --git a/drivers/arm-ffa/arm_ffa_prv.h b/drivers/arm-ffa/arm_ffa_prv.h
> new file mode 100644
> index 0000000000..44f258addb
> --- /dev/null
> +++ b/drivers/arm-ffa/arm_ffa_prv.h
> @@ -0,0 +1,193 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#ifndef __ARM_FFA_PRV_H
> +#define __ARM_FFA_PRV_H
> +
> +#include <arm_ffa.h>
> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
> +#include <dm/read.h>
> +
> +/*
> + * This header is private. It is exclusively used by the FF-A driver
> + */
> +
> +/* FF-A core driver name */
> +#define FFA_DRV_NAME "arm_ffa"
> +
> +/* FF-A driver version definitions */
> +
> +#define MAJOR_VERSION_MASK		GENMASK(30, 16)
> +#define MINOR_VERSION_MASK		GENMASK(15, 0)
> +#define GET_FFA_MAJOR_VERSION(x)		\
> +				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> +#define GET_FFA_MINOR_VERSION(x)		\
> +				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> +#define PACK_VERSION_INFO(major, minor)			\
> +	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
> +	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> +
> +#define FFA_MAJOR_VERSION		(1)
> +#define FFA_MINOR_VERSION		(0)
> +#define FFA_VERSION_1_0		\
> +			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> +
> +/* Endpoint ID mask (u-boot endpoint ID) */
> +
> +#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
> +#define GET_SELF_ENDPOINT_ID(x)		\
> +			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> +
> +#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
> +#define PREP_SELF_ENDPOINT_ID(x)		\
> +			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> +
> +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> +
> +#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
> +#define PREP_PART_ENDPOINT_ID(x)		\
> +			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> +
> +/* The FF-A SMC function prototype definition */
> +
> +typedef void (*invoke_ffa_fn_t)(unsigned long a0, unsigned long a1,
> +			unsigned long a2, unsigned long a3, unsigned long a4,
> +			unsigned long a5, unsigned long a6, unsigned long a7,
> +			struct arm_smccc_res *res);
> +
> +/**
> + * enum ffa_conduit - Arm FF-A conduits supported by the Arm FF-A driver
> + * Currently only SMC32 is supported.
> + */
> +enum ffa_conduit {
> +	FFA_CONDUIT_SMC = 0,
> +};

Why is this enum needed?

> +
> +/**
> + * FFA_DECLARE_ARGS - FF-A functions local variables
> + * @a0-a7:	local variables used to set registers x0-x7
> + * @res:	the structure hosting the FF-A function return data
> + *
> + * A helper macro for declaring local variables for the FF-A functions  arguments.
> + * The x0-x7 registers are used to exchange data with the secure world.
> + * But, only the bottom 32-bit of thes registers contains the data.
> + */
> +#define FFA_DECLARE_ARGS \
> +	unsigned long a0 = 0; \
> +	unsigned long a1 = 0; \
> +	unsigned long a2 = 0; \
> +	unsigned long a3 = 0; \
> +	unsigned long a4 = 0; \
> +	unsigned long a5 = 0; \
> +	unsigned long a6 = 0; \
> +	unsigned long a7 = 0; \
> +	struct arm_smccc_res res = {0}
> +
> +/* FF-A error codes */
> +#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_INTERRUPTED				(-5)
> +#define FFA_ERR_STAT_DENIED				(-6)
> +#define FFA_ERR_STAT_RETRY				(-7)
> +#define FFA_ERR_STAT_ABORTED				(-8)
> +
> +/**
> + * struct ffa_features_desc - FF-A functions features
> + * @func_id:	FF-A function
> + * @field1:	features read from register w2
> + * @field2:	features read from register w3
> + *
> + * Data structure describing the features of the  FF-A functions queried by
> + * FFA_FEATURES
> + */
> +struct ffa_features_desc {
> +	u32 func_id;
> +	u32 field1;
> +	u32 field2;
> +};
> +
> +/**
> + * enum ffa_rxtx_buf_sizes - minimum sizes supported
> + * for the RX/TX buffers
> + */
> +enum ffa_rxtx_buf_sizes {
> +	RXTX_4K,
> +	RXTX_64K,
> +	RXTX_16K
> +};
> +
> +/*
> + * Number of the FF-A interfaces features descriptors
> + * currently only FFA_RXTX_MAP descriptor is supported
> + */
> +#define FFA_FEATURE_DESC_CNT (1)
> +
> +/**
> + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> + * @rxbuf:	virtual address of the RX buffer
> + * @txbuf:	virtual address of the TX buffer
> + *
> + * Data structure hosting the virtual addresses of the mapped RX/TX buffers
> + * These addresses are used by the FF-A functions that use the RX/TX buffers
> + */
> +struct ffa_rxtxpair {
> +	u64 rxbuf; /* virtual address */
> +	u64 txbuf; /* virtual address */
> +};
> +
> +/**
> + * struct ffa_partition_desc - the secure partition descriptor
> + * @info:	partition information
> + * @UUID:	UUID
> + *
> + * Each partition has its descriptor containing the partitions information and the UUID
> + */
> +struct ffa_partition_desc {
> +	struct ffa_partition_info info;
> +	union ffa_partition_uuid UUID;
> +};
> +
> +/**
> + * struct ffa_partitions - descriptors for all secure partitions
> + * @count:	The number of partitions descriptors
> + * @descs	The partitions descriptors table
> + *
> + * This data structure contains the partitions descriptors table
> + */
> +struct ffa_partitions {
> +	u32 count;
> +	struct ffa_partition_desc *descs; /* virtual address */
> +};
> +
> +/**
> + * struct 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
> + * @conduit:	The selected conduit
> + * @invoke_ffa_fn:	The function executing the FF-A function
> + * @features:	Table of the FF-A functions having features
> + *
> + * The driver data structure hosting all resident data.
> + */
> +struct ffa_prvdata {
> +	struct udevice *dev;
> +	u32 fwk_version;
> +	u16 id;
> +	struct ffa_partitions partitions;
> +	struct ffa_rxtxpair pair;
> +	enum ffa_conduit conduit;
> +	invoke_ffa_fn_t invoke_ffa_fn;
> +	struct ffa_features_desc features[FFA_FEATURE_DESC_CNT];
> +};
> +
> +#endif
> diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c
> new file mode 100644
> index 0000000000..09e4eb753a
> --- /dev/null
> +++ b/drivers/arm-ffa/core.c
> @@ -0,0 +1,1349 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include "arm_ffa_prv.h"
> +#include <asm/global_data.h>
> +#include <asm/io.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 <log.h>
> +#include <malloc.h>
> +#include <mapmem.h>
> +#include <string.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/**
> + * The device private data structure containing all the resident
> + * data read from secure world
> + */
> +struct ffa_prvdata __ffa_runtime_data ffa_priv_data = {0};
> +
> +/*
> + * Driver functions
> + */
> +
> +/**
> + * ffa_get_device - create, bind and probe the arm_ffa device
> + *
> + * This boot time function makes sure the arm_ffa device is
> + * created, bound to this driver, probed and ready to use.
> + * Arm FF-A transport is implemented through a single u-boot
> + * device managing the FF-A bus (arm_ffa).
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +int ffa_get_device(void)
> +{
> +	int ret;
> +
> +	if (ffa_priv_data.dev)
> +		return FFA_ERR_STAT_SUCCESS;
> +
> +	ret = device_bind(dm_root(),
> +			  DM_DRIVER_GET(arm_ffa),
> +			  FFA_DRV_NAME,
> +			  NULL,
> +			  ofnode_null(),
> +			  &ffa_priv_data.dev);
> +	if (ret) {
> +		ffa_priv_data.dev = NULL;
> +		return ret;
> +	}
> +
> +	/* The FF-A bus discovery succeeds when probing is successful */
> +	ret = device_probe(ffa_priv_data.dev);
> +	if (ret) {
> +		ffa_err("can not probe  the device");
> +		device_unbind(ffa_priv_data.dev);
> +		ffa_priv_data.dev = NULL;
> +		return ret;
> +	}
> +
> +	return FFA_ERR_STAT_SUCCESS;
> +}
> +
> +/**
> + * ffa_get_version - FFA_VERSION handler function
> + *
> + * This is the boot time function that implements FFA_VERSION FF-A function
> + * to get from the secure world the FF-A framework version
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_get_version(void)
> +{
> +	u16 major, minor;
> +
> +	FFA_DECLARE_ARGS;
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	a0 = FFA_VERSION;
> +	a1 = FFA_VERSION_1_0;
> +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> +
> +	if (res.a0 == FFA_ERR_STAT_NOT_SUPPORTED) {
> +		ffa_err("A Firmware Framework implementation does not exist");
> +		return -EOPNOTSUPP;
> +	}
> +
> +	major = GET_FFA_MAJOR_VERSION(res.a0);
> +	minor = GET_FFA_MINOR_VERSION(res.a0);
> +
> +	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> +		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> +
> +	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
> +		ffa_info("Versions are compatible ");
> +
> +		ffa_priv_data.fwk_version = res.a0;
> +
> +		return FFA_ERR_STAT_SUCCESS;
> +	}
> +
> +	ffa_info("Versions are incompatible ");

This is an error, perhaps better to use ffa_err() instead. And mention
the versions in question also since the info level might be disabled.

> +	return -EPROTONOSUPPORT;
> +}
> +
> +/**
> + * ffa_get_endpoint_id - FFA_ID_GET handler function
> + *
> + * This is the boot time function that implements FFA_ID_GET FF-A function
> + * to get from the secure world u-boot endpoint ID

This is to get the vm id from an eventual hypervisor, or 0 if there
isn't any hypervisor.

> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_get_endpoint_id(void)
> +{
> +	FFA_DECLARE_ARGS;
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	a0 = FFA_ID_GET;
> +
> +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> +
> +	switch (res.a0) {
> +	case FFA_ERROR:
> +	{
> +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
> +			ffa_err("This function is not implemented at this FF-A instance");
> +			return -EOPNOTSUPP;
> +		}
> +
> +		ffa_err("Undefined error code (%d)", ((int)res.a2));
> +		return -EINVAL;
> +	}

Are these extra braces really needed? Same below.

> +	case FFA_SUCCESS:
> +	{
> +		ffa_priv_data.id = GET_SELF_ENDPOINT_ID(res.a2);
> +		ffa_info("endpoint ID is %u", ffa_priv_data.id);
> +
> +		return FFA_ERR_STAT_SUCCESS;
> +	}
> +	default:
> +	{
> +		ffa_err("Undefined response function (0x%lx)", res.a0);
> +		return -EINVAL;
> +	}
> +	}
> +}
> +
> +/**
> + * ffa_get_features_desc - returns the features descriptor of the specified
> + *						FF-A function
> + * @func_id:	the FF-A function which the features are to be retrieved
> + *
> + * This is a boot time function that searches the features descriptor of the
> + * specified FF-A function
> + *
> + * Return:
> + *
> + * When found, the address of the features descriptor is returned. Otherwise, NULL.
> + */
> +static struct ffa_features_desc *ffa_get_features_desc(u32 func_id)
> +{
> +	u32 desc_idx;
> +
> +	/*
> +	 * search for the descriptor of the selected FF-A interface
> +	 */
> +	for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
> +		if (ffa_priv_data.features[desc_idx].func_id == func_id)
> +			return &ffa_priv_data.features[desc_idx];
> +
> +	return NULL;
> +}
> +
> +/**
> + * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP
> + *							argument
> + *
> + * This is the boot time function that implements FFA_FEATURES FF-A function
> + * to retrieve the FFA_RXTX_MAP features
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_get_rxtx_map_features(void)
> +{
> +	FFA_DECLARE_ARGS;
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	a0 = FFA_FEATURES;
> +	a1 = FFA_RXTX_MAP;
> +
> +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> +
> +	switch (res.a0) {
> +	case FFA_ERROR:
> +	{
> +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
> +			ffa_err("FFA_RXTX_MAP is not implemented at this FF-A instance");
> +			return -EOPNOTSUPP;
> +		}
> +
> +		ffa_err("Undefined error code (%d)", ((int)res.a2));
> +		return -EINVAL;
> +	}
> +	case FFA_SUCCESS:
> +	{
> +		u32 desc_idx;
> +
> +		/*
> +		 * search for an empty descriptor
> +		 */
> +		for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
> +			if (!ffa_priv_data.features[desc_idx].func_id) {
> +				/*
> +				 * populate the descriptor with
> +				 * the interface features data
> +				 */
> +				ffa_priv_data.features[desc_idx].func_id =
> +					FFA_RXTX_MAP;
> +				ffa_priv_data.features[desc_idx].field1 =
> +					res.a2;
> +
> +				ffa_info("FFA_RXTX_MAP features data 0x%lx",
> +					 res.a2);

This seems a bit more complicated than necessary. How about just save
the block size in a separate fields in ffa_priv_data? That would also
make it easier to understand what this value is without looking it up in
the spec to remind oneself.

> +
> +				return FFA_ERR_STAT_SUCCESS;
> +			}
> +
> +		ffa_err("Cannot save FFA_RXTX_MAP features data. Descriptors table full");
> +		return -ENOBUFS;
> +	}
> +	default:
> +	{
> +		ffa_err("Undefined response function (0x%lx)",
> +			res.a0);
> +		return -EINVAL;
> +	}
> +	}
> +}
> +
> +/**
> + * ffa_get_rxtx_buffers_pages_cnt - reads from the features data descriptors
> + *						the minimum number of pages in each of the RX/TX
> + *						buffers
> + * @buf_4k_pages: Pointer to the minimum number of pages
> + *
> + * This is the boot time function that  returns the minimum number of pages
> + *  in each of the RX/TX buffers
> + *
> + * Return:
> + *
> + * buf_4k_pages points to the returned number of pages
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_get_rxtx_buffers_pages_cnt(size_t *buf_4k_pages)
> +{
> +	struct ffa_features_desc *desc = NULL;
> +
> +	if (!buf_4k_pages)
> +		return -EINVAL;
> +
> +	desc = ffa_get_features_desc(FFA_RXTX_MAP);
> +	if (!desc)
> +		return -EINVAL;
> +
> +	switch (desc->field1) {
> +	case RXTX_4K:
> +		*buf_4k_pages = 1;
> +		break;
> +	case RXTX_16K:
> +		*buf_4k_pages = 4;
> +		break;
> +	case RXTX_64K:
> +		*buf_4k_pages = 16;
> +		break;
> +	default:
> +		ffa_err("RX/TX buffer size not supported");
> +		return -EINVAL;
> +	}
> +
> +	return FFA_ERR_STAT_SUCCESS;
> +}
> +
> +/**
> + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> + *			  buffers
> + *
> + * This is the boot time function used to free the RX/TX buffers
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_free_rxtx_buffers(size_t buf_4k_pages)
> +{
> +	efi_status_t free_rxbuf_ret, free_txbuf_ret;
> +
> +	ffa_info("Freeing RX/TX buffers");
> +
> +	free_rxbuf_ret = efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
> +	free_txbuf_ret = efi_free_pages(ffa_priv_data.pair.txbuf, buf_4k_pages);
> +
> +	if (free_rxbuf_ret != EFI_SUCCESS || free_txbuf_ret != EFI_SUCCESS) {
> +		ffa_err("Failed to free RX/TX buffers (rx: %lu , tx: %lu)",
> +			free_rxbuf_ret,
> +			free_txbuf_ret);
> +		return -EINVAL;
> +	}
> +
> +	ffa_priv_data.pair.rxbuf = 0;
> +	ffa_priv_data.pair.txbuf = 0;
> +
> +	return FFA_ERR_STAT_SUCCESS;
> +}
> +
> +/**
> + * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
> + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> + *			  buffers
> + *
> + * This is the boot time function used by ffa_map_rxtx_buffers to allocate
> + * the RX/TX buffers before mapping them
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_alloc_rxtx_buffers(size_t buf_4k_pages)
> +{
> +#if CONFIG_IS_ENABLED(EFI_LOADER)
> +
> +	efi_status_t efi_ret;
> +	void *virt_txbuf;
> +	void *virt_rxbuf;
> +
> +	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
> +		 buf_4k_pages);
> +
> +	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> +				     EFI_BOOT_SERVICES_DATA,
> +				     buf_4k_pages,
> +				     &ffa_priv_data.pair.rxbuf);
> +
> +	if (efi_ret != EFI_SUCCESS) {
> +		ffa_priv_data.pair.rxbuf = 0;
> +		ffa_err("Failure to allocate RX buffer (EFI error: 0x%lx)",
> +			efi_ret);
> +
> +		return -ENOBUFS;
> +	}
> +
> +	ffa_info("RX buffer at virtual address 0x%llx",
> +		 ffa_priv_data.pair.rxbuf);
> +
> +	virt_rxbuf = (void *)ffa_priv_data.pair.rxbuf;
> +
> +	/*
> +	 * make sure the buffer is clean before use
> +	 */
> +	memset(virt_rxbuf, 0, buf_4k_pages * SZ_4K);
> +
> +	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> +				     EFI_RUNTIME_SERVICES_DATA,
> +				     buf_4k_pages,
> +				     &ffa_priv_data.pair.txbuf);
> +
> +	if (efi_ret != EFI_SUCCESS) {
> +		efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
> +		ffa_priv_data.pair.rxbuf = 0;
> +		ffa_priv_data.pair.txbuf = 0;
> +		ffa_err("Failure to allocate the TX buffer (EFI error: 0x%lx)"
> +			, efi_ret);
> +
> +		return -ENOBUFS;
> +	}
> +
> +	ffa_info("TX buffer at virtual address 0x%llx",
> +		 ffa_priv_data.pair.txbuf);
> +
> +	virt_txbuf = (void *)ffa_priv_data.pair.txbuf;
> +
> +	/*
> +	 * make sure the buffer is clean before use
> +	 */
> +	memset(virt_txbuf, 0, buf_4k_pages * SZ_4K);
> +
> +	return FFA_ERR_STAT_SUCCESS;
> +
> +#else
> +	return -ENOBUFS;
> +#endif
> +}
> +
> +/**
> + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> + *			  buffers
> + *
> + * This is the boot time function that implements FFA_RXTX_MAP FF-A function
> + * to map the RX/TX buffers
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_map_rxtx_buffers(size_t buf_4k_pages)
> +{
> +	int ret;
> +
> +	FFA_DECLARE_ARGS;
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	ret = ffa_alloc_rxtx_buffers(buf_4k_pages);
> +	if (ret != FFA_ERR_STAT_SUCCESS)
> +		return ret;
> +
> +	a0 = FFA_RXTX_MAP;
> +	a1 = ffa_priv_data.pair.txbuf;
> +	a2 = ffa_priv_data.pair.rxbuf;
> +	a3 = buf_4k_pages;
> +
> +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> +
> +	switch (res.a0) {
> +	case FFA_ERROR:
> +	{
> +		switch (((int)res.a2)) {
> +		case FFA_ERR_STAT_INVALID_PARAMETERS:
> +			ffa_err("One or more fields in input parameters is incorrectly encoded");
> +			ret = -EPERM;
> +			break;
> +		case FFA_ERR_STAT_NO_MEMORY:
> +			ffa_err("Not enough memory");
> +			ret = -ENOMEM;
> +			break;
> +		case FFA_ERR_STAT_DENIED:
> +			ffa_err("Buffer pair already registered");
> +			ret = -EACCES;
> +			break;
> +		case FFA_ERR_STAT_NOT_SUPPORTED:
> +			ffa_err("This function is not implemented at this FF-A instance");
> +			ret = -EOPNOTSUPP;
> +			break;
> +		default:
> +			ffa_err("Undefined error (%d)",
> +				((int)res.a2));
> +			ret = -EINVAL;
> +		}

How about lookup table like in the kernel instead? It seems that this
kind of translation will be needed a few times.


> +		break;
> +	}
> +	case FFA_SUCCESS:
> +		ffa_info("RX/TX buffers mapped");
> +		return FFA_ERR_STAT_SUCCESS;
> +	default:
> +		ffa_err("Undefined response function (0x%lx)",
> +			res.a0);
> +		ret = -EINVAL;
> +	}
> +
> +	ffa_free_rxtx_buffers(buf_4k_pages);
> +
> +	return ret;
> +}
> +
> +/**
> + * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
> + *
> + * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function
> + * to unmap the RX/TX buffers
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_unmap_rxtx_buffers(void)
> +{
> +	FFA_DECLARE_ARGS;
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	a0 = FFA_RXTX_UNMAP;
> +	a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id);
> +
> +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> +
> +	switch (res.a0) {
> +	case FFA_ERROR:
> +	{
> +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
> +			panic("[FFA] FFA_RXTX_UNMAP is not implemented at this FF-A instance\n");
> +		else if (((int)res.a2) == FFA_ERR_STAT_INVALID_PARAMETERS)
> +			panic("[FFA] There is no buffer pair registered on behalf of the caller\n");
> +		else
> +			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
> +	}
> +	case FFA_SUCCESS:
> +	{
> +		size_t buf_4k_pages = 0;
> +		int ret;
> +
> +		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
> +		if (ret != FFA_ERR_STAT_SUCCESS)
> +			panic("[FFA] RX/TX buffers unmapped but failure in getting pages count\n");
> +
> +		ret = ffa_free_rxtx_buffers(buf_4k_pages);
> +		if (ret != FFA_ERR_STAT_SUCCESS)
> +			panic("[FFA] RX/TX buffers unmapped but failure in freeing the memory\n");
> +
> +		ffa_info("RX/TX buffers unmapped and memory freed");
> +
> +		return FFA_ERR_STAT_SUCCESS;
> +	}
> +	default:
> +		panic("[FFA] Undefined response function (0x%lx)", res.a0);
> +	}
> +}
> +
> +/**
> + * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
> + *
> + * This is the boot time function that invokes FFA_RX_RELEASE FF-A function
> + * to release the ownership of the RX buffer
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_release_rx_buffer(void)
> +{
> +	FFA_DECLARE_ARGS;
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	a0 = FFA_RX_RELEASE;
> +
> +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> +
> +	switch (res.a0) {
> +	case FFA_ERROR:
> +	{
> +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
> +			panic("[FFA] FFA_RX_RELEASE is not implemented at this FF-A instance\n");
> +		else if (((int)res.a2) == FFA_ERR_STAT_DENIED)
> +			panic("[FFA] Caller did not have ownership of the RX buffer\n");
> +		else
> +			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
> +	}
> +	case FFA_SUCCESS:
> +		return FFA_ERR_STAT_SUCCESS;
> +
> +	default:
> +		panic("[FFA] Undefined response function (0x%lx)\n", res.a0);
> +	}
> +}
> +
> +/**
> + * ffa_uuid_are_identical - checks whether two given UUIDs are identical
> + * @uuid1: first UUID
> + * @uuid2: second UUID
> + *
> + * This is a boot time function used by ffa_read_partitions_info to search
> + * for a UUID in the partitions descriptors table
> + *
> + * Return:
> + *
> + * 1 when UUIDs match. Otherwise, 0
> + */
> +int ffa_uuid_are_identical(const union ffa_partition_uuid *uuid1,
> +			   const union ffa_partition_uuid *uuid2)
> +{
> +	if (!uuid1 || !uuid2)
> +		return 0;
> +
> +	return (!memcmp(uuid1, uuid2, sizeof(union ffa_partition_uuid)));
> +}
> +
> +/**
> + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> + *							and saves it in the private structure
> + * @count: The number of partitions queried
> + * @part_uuid: Pointer to the partition(s) UUID
> + *
> + * This is the boot time function that reads the partitions information
> + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> + * data structure.
> + *
> + * Return:
> + *
> + * The private data structure is updated with the partition(s) information
> + * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
> + */
> +static int ffa_read_partitions_info(u32 count, union ffa_partition_uuid *part_uuid)
> +{
> +	if (!count) {
> +		ffa_err("No partition detected");
> +		return -ENODATA;
> +	}
> +
> +	ffa_info("Reading partitions data from the RX buffer");
> +
> +#if CONFIG_IS_ENABLED(EFI_LOADER)
> +
> +	if (!part_uuid) {
> +		/*
> +		 * querying information of all partitions
> +		 */
> +		u64 data_pages;
> +		u64 data_bytes;
> +		efi_status_t efi_ret;
> +		size_t buf_4k_pages = 0;
> +		u32 desc_idx;
> +		struct ffa_partition_info *parts_info;
> +		int ret;
> +
> +		data_bytes = count * sizeof(struct ffa_partition_desc);
> +		data_pages = efi_size_in_pages(data_bytes);
> +
> +		/*
> +		 * get the RX buffer size in pages
> +		 */
> +		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
> +		if (ret != FFA_ERR_STAT_SUCCESS) {
> +			ffa_err("Can not get the RX buffer size (error %d)", ret);
> +			return ret;
> +		}
> +
> +		if (data_pages > buf_4k_pages) {
> +			ffa_err("Partitions data size exceeds the RX buffer size:");
> +			ffa_err("    Sizes in pages: data %llu , RX buffer %lu ",
> +				data_pages,
> +				buf_4k_pages);
> +
> +			return -ENOMEM;
> +		}
> +
> +		efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> +					     EFI_RUNTIME_SERVICES_DATA,
> +					     data_pages,
> +					     (u64 *)&ffa_priv_data.partitions.descs);
> +
> +		if (efi_ret != EFI_SUCCESS) {
> +			ffa_priv_data.partitions.descs = NULL;
> +
> +			ffa_err("Cannot  allocate partitions data buffer (EFI error 0x%lx)",
> +				efi_ret);
> +
> +			return -ENOBUFS;
> +		}
> +
> +		/*
> +		 * make sure the buffer is clean before use
> +		 */
> +		memset(ffa_priv_data.partitions.descs, 0,
> +		       data_pages * SZ_4K);
> +
> +		parts_info = (struct ffa_partition_info *)ffa_priv_data.pair.rxbuf;
> +
> +		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
> +			ffa_priv_data.partitions.descs[desc_idx].info =
> +				parts_info[desc_idx];
> +
> +			ffa_info("Partition ID %x : info cached",
> +				 ffa_priv_data.partitions.descs[desc_idx].info.id);
> +		}
> +
> +		ffa_priv_data.partitions.count = count;
> +
> +		ffa_info("%d partition(s) found and cached", count);
> +
> +	} else {
> +		u32 rx_desc_idx, cached_desc_idx;
> +		struct ffa_partition_info *parts_info;
> +		u8 desc_found;
> +
> +		parts_info = (struct ffa_partition_info *)ffa_priv_data.pair.rxbuf;
> +
> +		/*
> +		 * search for the SP IDs read from the RX buffer
> +		 * in the already cached SPs.
> +		 * Update the UUID when ID found.
> +		 */
> +		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
> +			desc_found = 0;
> +
> +			/*
> +			 * search the current ID in the cached partitions
> +			 */
> +			for (cached_desc_idx = 0;
> +			     cached_desc_idx < ffa_priv_data.partitions.count;
> +			     cached_desc_idx++) {
> +				/*
> +				 * save the UUID
> +				 */
> +				if (ffa_priv_data.partitions.descs[cached_desc_idx].info.id ==
> +				    parts_info[rx_desc_idx].id) {
> +					ffa_priv_data.partitions.descs[cached_desc_idx].UUID =
> +						*part_uuid;
> +
> +					desc_found = 1;
> +					break;
> +				}
> +			}
> +
> +			if (!desc_found)
> +				return -ENODATA;
> +		}
> +	}
> +#else
> +#warning "arm_ffa: reading FFA_PARTITION_INFO_GET data not implemented"
> +#endif
> +
> +	return  FFA_ERR_STAT_SUCCESS;
> +}
> +
> +/**
> + * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET
> + *							and saves partitions data

Strange indentation.

> + * @part_uuid: Pointer to the partition(s) UUID
> + * @pcount: Pointer to the number of partitions variable filled when querying
> + *
> + * This is the boot time function that executes the FFA_PARTITION_INFO_GET
> + * to query the partitions data. Then, it calls ffa_read_partitions_info
> + * to save the data in the private data structure.
> + *
> + * After reading the data the RX buffer is released using ffa_release_rx_buffer
> + *
> + * Return:
> + *
> + * When part_uuid is NULL, all partitions data are retrieved from secure world
> + * When part_uuid is non NULL, data for partitions matching the given UUID are
> + * retrieved and the number of partitions is returned
> + * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
> + */
> +static int ffa_query_partitions_info(union ffa_partition_uuid *part_uuid,
> +				     u32 *pcount)
> +{
> +	unsigned long a0 = 0;
> +	union ffa_partition_uuid query_uuid = {0};
> +	unsigned long a5 = 0;
> +	unsigned long a6 = 0;
> +	unsigned long a7 = 0;
> +	struct arm_smccc_res res = {0};
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		panic("[FFA] no private data found\n");
> +
> +	a0 = FFA_PARTITION_INFO_GET;

Why no initialize a0 with with value above instead?

> +
> +	/*
> +	 * If a UUID is specified. Information for one or more
> +	 * partitions in the system is queried. Otherwise, information
> +	 * for all installed partitions is queried
> +	 */
> +
> +	if (part_uuid) {
> +		if (!pcount)
> +			return -EINVAL;
> +
> +		query_uuid = *part_uuid;
> +	}
> +
> +	ffa_priv_data.invoke_ffa_fn(a0, query_uuid.words.a1, query_uuid.words.a2,
> +				    query_uuid.words.a3, query_uuid.words.a4,
> +				    a5, a6, a7, &res);
> +
> +	switch (res.a0) {
> +	case FFA_ERROR:
> +	{
> +		switch (((int)res.a2)) {
> +		case FFA_ERR_STAT_INVALID_PARAMETERS:
> +			ffa_err("Unrecognized UUID");
> +			return -EPERM;
> +		case FFA_ERR_STAT_NO_MEMORY:
> +			ffa_err("Results cannot fit in RX buffer of the caller");
> +			return -ENOMEM;
> +		case FFA_ERR_STAT_DENIED:
> +			ffa_err("Callee is not in a state to handle this request");
> +			return -EACCES;
> +		case FFA_ERR_STAT_NOT_SUPPORTED:
> +			ffa_err("This function is not implemented at this FF-A instance");
> +			return -EOPNOTSUPP;
> +		case FFA_ERR_STAT_BUSY:
> +			ffa_err("RX buffer of the caller is not free");
> +			return -EBUSY;
> +		default:
> +			ffa_err("Undefined error (%d)", ((int)res.a2));
> +			return -EINVAL;
> +		}
> +	}
> +	case FFA_SUCCESS:
> +	{
> +		int ret;
> +
> +		/*
> +		 * res.a2 contains the count of partition information descriptors
> +		 * populated in the RX buffer
> +		 */
> +		if (res.a2) {
> +			ret = ffa_read_partitions_info(res.a2, part_uuid);
> +			if (ret)
> +				ffa_err("Failed to read partition(s) data , error (%d)", ret);
> +		}
> +
> +		/*
> +		 * return the SP count
> +		 */
> +		if (part_uuid) {
> +			if (!ret)
> +				*pcount = res.a2;
> +			else
> +				*pcount = 0;
> +		}
> +		/*
> +		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
> +		 * is assigned to the consumer (u-boot). So, we need to give
> +		 * the ownership back to the secure world
> +		 */

if there's a hypervisor we're returning the buffer to the hypervisor instead.
how about "... back to the SPM or hypervisor"?

> +		ret = ffa_release_rx_buffer();
> +
> +		if (!part_uuid && !res.a2) {
> +			ffa_err("[FFA] no partition installed in the system");
> +			return -ENODEV;
> +		}
> +
> +		return ret;
> +	}
> +	default:
> +		ffa_err("Undefined response function (0x%lx)", res.a0);
> +		return  -EINVAL;
> +	}
> +}
> +
> +/**
> + * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
> + * @func_data: Pointer to the FF-A function arguments container structure.
> + * The passed arguments:
> + * Mode 1: When getting from the driver the number of
> + *	secure partitions:
> + *	@data0_size: UUID size
> + *	@data0: pointer to the UUID (little endian)
> + *	@data1_size: size of the number of partitions
> + *				variable
> + *	@data1: pointer to the number of partitions
> + *			 variable. The variable will be set
> + *			 by the driver
> + * Mode 2: When requesting the driver to return the
> + *	partitions information:
> + *	@data0_size: UUID size
> + *	@data0: pointer to the UUID (little endian)
> + *	@data1_size: size of the SPs information buffer
> + *	@data1: pointer to SPs information buffer
> + *		(allocated by the client).
> + *		The buffer will be filled by the driver
> + *
> + * This is the boot time function that queries the secure partition data from
> + * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
> + * FF-A function to query the partition information from secure world.
> + *
> + * A client of the FF-A driver should know the UUID of the service it wants to
> + * access. It should use the UUID to request the FF-A driver to provide the
> + * partition(s) information of the service. The FF-A driver uses
> + * PARTITION_INFO_GET to obtain this information. This is implemented through
> + * ffa_get_partitions_info function.
> + * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
> + * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
> + * They are not saved (already done). We only update the UUID in the cached area.
> + * This assumes that partitions data does not change in the secure world.
> + * Otherwise u-boot will have an outdated partition data. The benefit of caching
> + * the information in the FF-A driver is to accommodate discovery after
> + * ExitBootServices().
> + *
> + * When invoked through a client request, ffa_get_partitions_info should be
> + * called twice. First call is to get from the driver the number of secure
> + * partitions (SPs) associated to a particular UUID.
> + * Then, the caller (client) allocates the buffer to host the SPs data and
> + * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
> + * buffer.
> + *
> + * To achieve the mechanism described above, ffa_get_partitions_info uses the
> + * following functions:
> + *		ffa_read_partitions_info
> + *		ffa_query_partitions_info
> + *
> + * Return:
> + *
> + * @data1: When pointing to the number of partitions variable, the number is
> + * set by the driver.
> + * When pointing to the partitions information buffer, the buffer will be
> + * filled by the driver.
> + *
> + * On success FFA_ERR_STAT_SUCCESS is returned. Otherwise, failure
> + */
> +static int ffa_get_partitions_info(struct ffa_interface_data *func_data)
> +{
> +	/*
> +	 * fill_data:
> +	 * 0: return the SP count
> +	 * 1: fill SP data and return it to the caller
> +	 * -1: undefined mode
> +	 */
> +	int fill_data = -1;
> +	u32 desc_idx, client_desc_idx;
> +	union ffa_partition_uuid *part_uuid;
> +	u32 client_desc_max_cnt;
> +	u32 parts_found = 0;
> +
> +	if (!func_data) {
> +		ffa_err("No function data provided");
> +		return -EINVAL;
> +	}
> +
> +	if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs)
> +		panic("[FFA] No partition installed\n");
> +
> +	if (func_data->data0_size == sizeof(union ffa_partition_uuid) &&
> +	    func_data->data0 &&
> +	    func_data->data1_size == sizeof(u32) &&
> +	    func_data->data1) {
> +		/*
> +		 * data0 (in): pointer to UUID
> +		 * data1 (in): pointer to SP count
> +		 * Out: SP count returned in the count variable pointed by data1
> +		 */
> +
> +		fill_data = 0;
> +
> +		ffa_info("Preparing for checking partitions count");
> +
> +	} else if ((func_data->data0_size == sizeof(union ffa_partition_uuid)) &&
> +		   func_data->data0 &&
> +		   (func_data->data1_size >= sizeof(struct ffa_partition_info)) &&
> +		   !(func_data->data1_size % sizeof(struct ffa_partition_info)) &&
> +		   func_data->data1) {
> +		/*
> +		 * data0 (in): pointer to UUID
> +		 * data1 (in): pointer to SPs descriptors buffer
> +		 *             (created by the client)
> +		 * Out: SPs descriptors returned in the buffer
> +		 *      pointed by data1
> +		 */
> +
> +		fill_data = 1;
> +
> +		client_desc_idx = 0;
> +
> +		/*
> +		 * number of empty descriptors preallocated by the caller
> +		 */
> +		client_desc_max_cnt =
> +			func_data->data1_size / sizeof(struct ffa_partition_info);
> +
> +		ffa_info("Preparing for filling partitions info");
> +
> +	} else {
> +		ffa_err("Invalid function arguments provided");
> +		return -EINVAL;
> +	}
> +
> +	part_uuid = (union ffa_partition_uuid *)func_data->data0;
> +
> +	ffa_info("Searching partitions using the provided UUID");
> +
> +	/*
> +	 * search in the cached partitions
> +	 */
> +	for (desc_idx = 0;
> +	     desc_idx < ffa_priv_data.partitions.count;
> +	     desc_idx++) {
> +		if (ffa_uuid_are_identical(&ffa_priv_data.partitions.descs[desc_idx].UUID,
> +					   part_uuid)) {
> +			ffa_info("Partition ID %x matches the provided UUID",
> +				 ffa_priv_data.partitions.descs[desc_idx].info.id);
> +
> +			parts_found++;
> +
> +			if (fill_data) {
> +				/*
> +				 * trying to fill the partition info in data1
> +				 */
> +
> +				if (client_desc_idx < client_desc_max_cnt) {
> +					((struct ffa_partition_info *)
> +					 func_data->data1)[client_desc_idx++] =
> +						ffa_priv_data.partitions.descs[desc_idx].info;
> +					continue;
> +				}
> +
> +				ffa_err("Failed to fill the current descriptor client buffer full");
> +				return -ENOBUFS;
> +			}
> +		}
> +	}
> +
> +	if (!parts_found) {
> +		int ret;
> +
> +		ffa_info("No partition found. Querying framework ...");
> +
> +		ret = ffa_query_partitions_info(part_uuid, &parts_found);
> +
> +		if (ret == FFA_ERR_STAT_SUCCESS) {
> +			if (!fill_data) {
> +				*((u32 *)func_data->data1) = parts_found;
> +
> +				ffa_info("Number of partition(s) found matching the UUID: %d",
> +					 parts_found);
> +			} else {
> +				/*
> +				 * we want to read SPs info
> +				 */
> +
> +				/*
> +				 * If SPs data filled, retry searching SP info again
> +				 */
> +				if (parts_found)
> +					ret = ffa_get_partitions_info(func_data);
> +				else
> +					ret = -ENODATA;
> +			}
> +		}
> +
> +		return ret;
> +	}
> +
> +	/* partition(s) found */
> +	if (!fill_data)
> +		*((u32 *)func_data->data1) = parts_found;
> +
> +	return FFA_ERR_STAT_SUCCESS;
> +}
> +
> +/**
> + * ffa_cache_partitions_info - Queries and saves all secure partitions data
> + *
> + * This is a boot time function that invokes FFA_PARTITION_INFO_GET FF-A
> + * function to query from secure world all partitions information.
> + *
> + * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
> + * All installed partitions information are returned. We cache them in the
> + * resident private data structure and we keep the UUID field empty
> + * (in FF-A 1.0 UUID is not provided by the partition descriptor)
> + *
> + * This function is called at the device probing level.
> + * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_cache_partitions_info(void)
> +{
> +	return ffa_query_partitions_info(NULL, NULL);
> +}
> +
> +/**
> + * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> + * @func_data: Pointer to the FF-A function arguments container structure.
> + *					The passed arguments:
> + *						@data0_size: partition ID size
> + *						@data0: pointer to the partition ID
> + *						@data1_size: exchanged data size
> + *						@data1: pointer to the data buffer preallocated by
> + *								the client (in/out)
> + *
> + * This is the runtime function that implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * FF-A functions.
> + *
> + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> + * The response from the secure partition is handled by reading the
> + * FFA_MSG_SEND_DIRECT_RESP arguments.
> + *
> + * The maximum size of the data that can be exchanged is 20 bytes which is
> + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */

This API looks quite complicated. Wouldn't it be easier to let the
caller supply the struct ffa_send_direct_data *msg pointer directly
instead, like in the Linux kernel driver. The approach here prevents the
compiler from helping with type checks etc.

> +static int __ffa_runtime ffa_msg_send_direct_req(struct ffa_interface_data
> +						 *func_data)
> +{
> +	u16 dst_part_id;
> +	unsigned long a0 = 0;
> +	unsigned long a1 = 0;
> +	unsigned long a2 = 0;
> +	struct ffa_send_direct_data *msg;
> +	struct arm_smccc_res res = {0};
> +
> +	if (!ffa_priv_data.invoke_ffa_fn)
> +		return -ENODEV;
> +
> +	if (!func_data)
> +		return -EINVAL;
> +
> +	/* No partition installed */
> +	if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs)
> +		return -ENODEV;
> +
> +	/* Undefined interface parameters */
> +	if (func_data->data0_size != sizeof(u16) ||
> +	    !func_data->data0 ||
> +	    func_data->data1_size != FFA_MSG_SEND_DIRECT_MAX_SIZE ||

FFA_MSG_SEND_DIRECT_MAX_SIZE? It's more like FFA_MSG_SEND_DIRECT_ONLY_SIZE.

> +	    !func_data->data1)
> +		return -EINVAL;
> +
> +	dst_part_id = *((u16 *)func_data->data0);
> +	msg = func_data->data1;
> +
> +	a0 = FFA_MSG_SEND_DIRECT_REQ;
> +
> +	a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id) |
> +		PREP_PART_ENDPOINT_ID(dst_part_id);
> +
> +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2,
> +				    msg->a3,
> +				    msg->a4,
> +				    msg->a5,
> +				    msg->a6,
> +				    msg->a7,
> +				    &res);
> +
> +	while (res.a0 == FFA_INTERRUPT)
> +		ffa_priv_data.invoke_ffa_fn(FFA_RUN, res.a1,
> +					    0, 0, 0, 0, 0, 0,
> +					    &res);
> +
> +	switch (res.a0) {
> +	case FFA_ERROR:
> +	{
> +		switch (((int)res.a2)) {
> +		case FFA_ERR_STAT_INVALID_PARAMETERS:
> +			/* Invalid endpoint ID or non-zero reserved register */
> +			return -EPERM;
> +		case FFA_ERR_STAT_ABORTED:
> +			/* Message target ran into unexpected error and has aborted */
> +			return -ECONNABORTED;
> +		case FFA_ERR_STAT_DENIED:
> +			/* Callee is not in a state to handle this request */
> +			return -EACCES;
> +		case FFA_ERR_STAT_NOT_SUPPORTED:
> +			/* This function is not implemented at this FF-A instance */
> +			return -EOPNOTSUPP;
> +		case FFA_ERR_STAT_BUSY:
> +			/* Message target is busy */
> +			return -EBUSY;
> +		default:
> +			/* Undefined error */
> +			return -ENXIO;
> +		}
> +	}
> +	case FFA_SUCCESS:
> +
> +		/* Message sent with no response */
> +		return FFA_ERR_STAT_SUCCESS;
> +
> +	case FFA_MSG_SEND_DIRECT_RESP:
> +
> +		/*
> +		 * Message sent with response
> +		 * extract the 32-bit wide return data
> +		 */
> +		msg->a3 = (u32)res.a3;
> +		msg->a4 = (u32)res.a4;
> +		msg->a5 = (u32)res.a5;
> +		msg->a6 = (u32)res.a6;
> +		msg->a7 = (u32)res.a7;
> +
> +		return FFA_ERR_STAT_SUCCESS;
> +
> +	default:
> +		/* Undefined response function */
> +		return -ENOENT;
> +	}
> +}
> +
> +/**
> + * invoke_ffa_drv_api - The driver dispatcher function
> + * @func_id:	The FF-A function to be used
> + * @func_data:  Pointer to the FF-A function arguments container
> + *					structure. This also includes pointers to the
> + *					returned data needed by clients.
> + * The dispatcher is a runtime function that selects the FF-A function handler
> + * based on the input FF-A function ID.
> + * The input arguments are passed to the handler function.
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +int __ffa_runtime invoke_ffa_drv_api(u32 func_id,
> +				     struct ffa_interface_data *func_data)
> +{
> +	if (!ffa_priv_data.dev)
> +		return -ENODEV;
> +

I don't see the point with this funnel layer. It would in my opinion be
easier to have one function pointer for each of the provided FF-A
functions.

I wouldn't mind if the interface was a bit more like the interface
provided in the Linux kernel, at least the parts we're going to support
here. It would for sure help later when updating the OP-TEE driver to
use this FF-A driver.

> +	switch (func_id) {
> +	case FFA_PARTITION_INFO_GET:
> +		return ffa_get_partitions_info(func_data);
> +	case FFA_RXTX_UNMAP:
> +		return ffa_unmap_rxtx_buffers();
> +	case FFA_MSG_SEND_DIRECT_REQ:
> +		return ffa_msg_send_direct_req(func_data);
> +	default:
> +		/* Undefined FF-A interface */
> +		return -EINVAL;
> +	}
> +}
> +
> +/**
> + * ffa_set_conduit - Set the conduit
> + *
> + * This boot time function clears the private data structure and sets the conduit
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_set_conduit(void)
> +{
> +	ffa_priv_data.conduit = FFA_CONDUIT_SMC;
> +
> +	ffa_priv_data.invoke_ffa_fn = arm_ffa_smccc_smc;
> +
> +	ffa_info("Conduit is SMC");

What if there's a hypervisor? Then HVC should be used instead.

> +
> +	return FFA_ERR_STAT_SUCCESS;
> +}
> +
> +/**
> + * ffa_probe - The driver probe function
> + * @dev:	the arm_ffa device
> + *
> + * Probing is done at boot time and triggered by the uclass device discovery.
> + * At probe level the following actions are done:
> + *	- setting the conduit
> + *	- querying the FF-A framework version
> + *	- querying from secure world the u-boot endpoint ID
> + *	- querying from secure world the supported features of the specified FF-A calls
> + *	- mapping the RX/TX buffers
> + *	- querying from secure world all the partitions information
> + *
> + * All data queried from secure world is saved in the resident private data structure.
> + *
> + * The probe will fail if either FF-A framework is not detected or the
> + * FF-A requests are not behaving correctly. This ensures that the
> + * driver is not installed and its operations are not exported to the clients.
> + * However, once the driver is successfully probed and an FF-A anomaly is
> + * detected when clients invoke the driver operations, the driver cause
> + * u-boot to panic because the client would not know what to do in such conditions.
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_probe(struct udevice *dev)
> +{
> +	int ret;
> +	size_t buf_4k_pages = 0;
> +
> +	ret = ffa_set_conduit();
> +	if (ret != FFA_ERR_STAT_SUCCESS)
> +		return ret;
> +
> +	ret = ffa_get_version();
> +	if (ret != FFA_ERR_STAT_SUCCESS)
> +		return ret;
> +
> +	ret = ffa_get_endpoint_id();
> +	if (ret != FFA_ERR_STAT_SUCCESS)
> +		return ret;
> +
> +	ret = ffa_get_rxtx_map_features();
> +	if (ret != FFA_ERR_STAT_SUCCESS)
> +		return ret;
> +
> +	ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
> +	if (ret != FFA_ERR_STAT_SUCCESS)
> +		return ret;
> +
> +	ret = ffa_map_rxtx_buffers(buf_4k_pages);

This function only suceeds if compiled with EFI runtime support, so probing will always fail without EFI runtime support.

If compiled with EFI runtime support, how is this supposed to work with
the kernel FF-A driver? The FF-A framework only supports one buffer pair
per component and I don't see where the buffer pair is freed when U-Boot
is done.

> +	if (ret != FFA_ERR_STAT_SUCCESS)
> +		return ret;
> +
> +	ret = ffa_cache_partitions_info();
> +	if (ret != FFA_ERR_STAT_SUCCESS) {
> +		ffa_free_rxtx_buffers(buf_4k_pages);
> +		return ret;
> +	}
> +
> +	return FFA_ERR_STAT_SUCCESS;
> +}
> +
> +/**
> + * ffa_drv_ops - The driver operations runtime structure
> + * @invoke_func:	The driver dispatcher
> + */
> +struct ffa_ops __ffa_runtime_data ffa_drv_ops = {
> +	.invoke_func = invoke_ffa_drv_api
> +};
> +
> +/**
> + * ffa_device_get_ops - driver operations getter
> + *
> + * Return:
> + * This runtime function returns a pointer to the driver operations structure
> + */
> +const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void)
> +{
> +	return &ffa_drv_ops;
> +}
> +
> +/**
> + * Declaring the arm_ffa driver under UCLASS_FFA
> + */
> +
> +U_BOOT_DRIVER(arm_ffa) = {
> +	.name		= FFA_DRV_NAME,
> +	.id		= UCLASS_FFA,
> +	.probe		= ffa_probe,
> +};
> diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> new file mode 100644
> index 0000000000..98db01ee72
> --- /dev/null
> +++ b/include/arm_ffa.h
> @@ -0,0 +1,190 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#ifndef __ARM_FFA_H
> +#define __ARM_FFA_H
> +
> +#include <linux/arm-smccc.h>
> +#include <linux/printk.h>
> +
> +/*
> + * This header is public. It can be used by clients to access
> + * data structures and definitions they need
> + */
> +
> +/*
> + * Macros for displaying logs
> + */
> +
> +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> +
> +/*
> + * The driver operations success error code
> + */
> +#define FFA_ERR_STAT_SUCCESS				(0)
> +
> +#if CONFIG_IS_ENABLED(EFI_LOADER)
> +
> +#include <efi_loader.h>
> +
> +/*
> + * __ffa_runtime_data and __ffa_runtime - controls whether data/code are
> + * available after calling the EFI ExitBootServices service.
> + * Data/code tagged with these keywords are resident (available at boot time and
> + * at runtime)
> + */
> +
> +#define __ffa_runtime_data __efi_runtime_data
> +#define __ffa_runtime __efi_runtime
> +
> +#else
> +
> +#define __ffa_runtime_data
> +#define __ffa_runtime
> +
> +#endif
> +
> +/*
> + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> + */
> +
> +#define FFA_SMC(calling_convention, func_num)				\
> +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
> +			   ARM_SMCCC_OWNER_STANDARD, (func_num))
> +
> +#define FFA_SMC_32(func_num)	FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> +
> +#define FFA_VERSION				FFA_SMC_32(0x63)
> +#define FFA_ID_GET				FFA_SMC_32(0x69)
> +#define FFA_FEATURES				FFA_SMC_32(0x64)
> +#define FFA_PARTITION_INFO_GET				FFA_SMC_32(0x68)

Too much indentation, same below

> +#define FFA_RXTX_MAP				FFA_SMC_32(0x66)
> +#define FFA_RXTX_UNMAP				FFA_SMC_32(0x67)
> +#define FFA_RX_RELEASE				FFA_SMC_32(0x65)
> +#define FFA_MSG_SEND_DIRECT_REQ				FFA_SMC_32(0x6F)
> +#define FFA_MSG_SEND_DIRECT_RESP				FFA_SMC_32(0x70)
> +#define FFA_RUN				FFA_SMC_32(0x6D)
> +#define FFA_ERROR				FFA_SMC_32(0x60)
> +#define FFA_SUCCESS				FFA_SMC_32(0x61)
> +#define FFA_INTERRUPT				FFA_SMC_32(0x62)
> +
> +/*
> + * struct ffa_partition_info - Partition information descriptor
> + * @id:	Partition ID
> + * @exec_ctxt:	Execution context count
> + * @properties:	Partition properties
> + *
> + * Data structure containing information about partitions instantiated in the system
> + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> + */
> +struct  __packed ffa_partition_info {
> +	u16 id;
> +	u16 exec_ctxt;
> +/* partition supports receipt of direct requests */
> +#define FFA_PARTITION_DIRECT_RECV	BIT(0)
> +/* partition can send direct requests. */
> +#define FFA_PARTITION_DIRECT_SEND	BIT(1)
> +/* partition can send and receive indirect messages. */
> +#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
> +	u32 properties;
> +};
> +
> +/*
> + * struct ffa_send_direct_data - Data structure hosting the data
> + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * @a3-a7:	Data read/written from/to w3-w7 registers
> + *
> + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> + * or read from FFA_MSG_SEND_DIRECT_RESP
> + */
> +struct __packed ffa_send_direct_data {
> +	u32 a3; /* w3 */
> +	u32 a4; /* w4 */
> +	u32 a5; /* w5 */
> +	u32 a6; /* w6 */
> +	u32 a7; /* w7 */
> +};
> +
> +#define FFA_MSG_SEND_DIRECT_MAX_SIZE (sizeof(struct ffa_send_direct_data))
> +
> +/* UUID data size */
> +#define UUID_SIZE (16)
> +
> +/*
> + * union ffa_partition_uuid - Data union hosting the UUID
> + *							transmitted by FFA_PARTITION_INFO_GET
> + * @words:	data structure giving 32-bit words access to the UUID data
> + * @bytes:	data structure giving byte access to the UUID data
> + *
> + * The structure holds little-endian UUID data.
> + */
> +union ffa_partition_uuid {
> +	struct __packed words {
> +	u32 a1; /* w1 */
> +	u32 a2; /* w2 */
> +	u32 a3; /* w3 */
> +	u32 a4; /* w4 */
> +	} words;
> +	u8 bytes[UUID_SIZE];
> +};
> +
> +/**
> + * struct ffa_interface_data - generic FF-A interface data structure used to exchange
> + *							data between user layers and the 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 user layers can pass various types of data with different sizes.
> + * The driver internal functions can detect the nature of this data, verfy compliance
> + * then execute the request when appropriate.
> + */
> +struct ffa_interface_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 */
> +};
> +
> +/**
> + * struct ffa_ops - The driver operations structure
> + * @invoke_func:	function pointer to the invoke function
> + *
> + * The data structure providing all the operations supported by the driver.
> + * This structure is resident.
> + */
> +struct ffa_ops {
> +	/* the driver dispatcher */
> +	int (*invoke_func)(u32 func_id, struct ffa_interface_data *func_data);
> +};
> +
> +/**
> + * The device driver and the Uclass driver public functions
> + */
> +
> +/**
> + * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher
> + */
> +int __ffa_runtime ffa_get_invoke_func(u32 func_id,
> +				      struct ffa_interface_data *func_data);
> +
> +/**
> + * ffa_device_get_ops - driver operations getter
> + */
> +const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void);
> +
> +/**
> + * ffa_get_device - create, bind and probe the arm_ffa device
> + */
> +int ffa_get_device(void);
> +
> +/**
> + * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
> + */
> +int ffa_bus_discover(void);
> +#endif
> diff --git a/include/arm_ffa_helper.h b/include/arm_ffa_helper.h
> new file mode 100644
> index 0000000000..1cf68748f0
> --- /dev/null
> +++ b/include/arm_ffa_helper.h
> @@ -0,0 +1,45 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#ifndef __ARM_FFA_HELPER_H
> +#define __ARM_FFA_HELPER_H
> +
> +#include <arm_ffa.h>
> +
> +/*
> + * This header is public. Including this header provides all data structures
> + * and definitions needed by clients to use the FF-A transport driver
> + *
> + * It also provides helper functions allowing to pass data and invoke  FF-A functions
> + */
> +
> +/**
> + * ffa_helper_get_partitions_info - Wrapper function for FFA_PARTITION_INFO_GET
> + */
> +int ffa_helper_get_partitions_info(struct ffa_interface_data *func_data);
> +
> +/**
> + * ffa_helper_unmap_rxtx_buffers - Wrapper function for FFA_RXTX_UNMAP
> + */
> +int ffa_helper_unmap_rxtx_buffers(void);
> +
> +/**
> + * ffa_helper_msg_send_direct_req - Wrapper function for
> + *								FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + */
> +int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data
> +						 *func_data);
> +
> +/**
> + * ffa_helper_bus_discover - Wrapper function for FF-A bus discovery
> + */
> +int ffa_helper_bus_discover(void);
> +
> +/**
> + * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
> + */
> +int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin);
> +#endif
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 0e26e1d138..a1181b8f48 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -52,6 +52,7 @@ enum uclass_id {
>  	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
>  	UCLASS_ETH,		/* Ethernet device */
>  	UCLASS_ETH_PHY,		/* Ethernet PHY device */
> +	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
>  	UCLASS_FIRMWARE,	/* Firmware */
>  	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
>  	UCLASS_GPIO,		/* Bank of general-purpose I/O pins */
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index 7f2be23394..d58c7c104b 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -1,6 +1,8 @@
>  /* SPDX-License-Identifier: GPL-2.0 */
>  /*
>   * Copyright (c) 2015, Linaro Limited
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  #ifndef __LINUX_ARM_SMCCC_H
>  #define __LINUX_ARM_SMCCC_H
> @@ -57,13 +59,17 @@
>  #include <linux/types.h>
>  /**
>   * struct arm_smccc_res - Result from SMC/HVC call
> - * @a0-a3 result values from registers 0 to 3
> + * @a0-a7 result values from registers 0 to 7
>   */
>  struct arm_smccc_res {
>  	unsigned long a0;
>  	unsigned long a1;
>  	unsigned long a2;
>  	unsigned long a3;
> +	unsigned long a4;
> +	unsigned long a5;
> +	unsigned long a6;
> +	unsigned long a7;
>  };
>  
>  /**
> @@ -113,6 +119,26 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
>  			unsigned long a5, unsigned long a6, unsigned long a7,
>  			struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
>  
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +/**
> + * __arm_ffa_smccc_smc() - make SMC calls used for FF-A transport
> + * @a0-a7: arguments passed in 64-bit registers x0 to x7
> + * @res: result values from 64-bit registers x0 to x7
> + *
> + * This function is used to make SMC calls following SMC32 Calling Convention.
> + * The content of the supplied parameters is copied to registers x0 to x7 prior
> + * to the SMC instruction. The SMC call return data is 32-bit data read from
> + * registers x0 tp x7.
> + */
> +asmlinkage void __arm_ffa_smccc_smc(unsigned long a0, unsigned long a1,
> +				    unsigned long a2, unsigned long a3, unsigned long a4,
> +				    unsigned long a5, unsigned long a6, unsigned long a7,
> +				    struct arm_smccc_res *res);
> +
> +#define arm_ffa_smccc_smc __arm_ffa_smccc_smc
> +
> +#endif
> +

How about leaving the FF-A bit out of this and only have generic SMCCC
support? That would make it easier to bring in updates from Linux
without reinventing the wheel. I would also be nice to know which
version of the SMCCC we're using.

Cheers,
Jens

>  #define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
>  
>  #define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
> diff --git a/lib/Kconfig b/lib/Kconfig
> index effe735365..9006e8d44c 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -845,6 +845,7 @@ config SMBIOS_PARSER
>  source lib/efi/Kconfig
>  source lib/efi_loader/Kconfig
>  source lib/optee/Kconfig
> +source lib/arm-ffa/Kconfig
>  
>  config TEST_FDTDEC
>  	bool "enable fdtdec test"
> diff --git a/lib/Makefile b/lib/Makefile
> index 13fe5fb7a4..36f67cd94e 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_EFI) += efi/
>  obj-$(CONFIG_EFI_LOADER) += efi_driver/
>  obj-$(CONFIG_EFI_LOADER) += efi_loader/
>  obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/
> +obj-$(CONFIG_ARM_FFA_TRANSPORT_HELPERS) += arm-ffa/
>  obj-$(CONFIG_LZMA) += lzma/
>  obj-$(CONFIG_BZIP2) += bzip2/
>  obj-$(CONFIG_TIZEN) += tizen/
> diff --git a/lib/arm-ffa/Kconfig b/lib/arm-ffa/Kconfig
> new file mode 100644
> index 0000000000..79acbc5a8f
> --- /dev/null
> +++ b/lib/arm-ffa/Kconfig
> @@ -0,0 +1,6 @@
> +config ARM_FFA_TRANSPORT_HELPERS
> +	bool "Enable interface helpers for Arm Firmware Framework for Armv8-A"
> +	depends on ARM_FFA_TRANSPORT
> +	help
> +	  User layers call FF-A interfaces using helper functions which
> +	  pass the data and the FF-A function ID to the low level driver
> diff --git a/lib/arm-ffa/Makefile b/lib/arm-ffa/Makefile
> new file mode 100644
> index 0000000000..cba625fde4
> --- /dev/null
> +++ b/lib/arm-ffa/Makefile
> @@ -0,0 +1,8 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +#
> +
> +# This file only gets included when CONFIG_ARM_FFA_TRANSPORT_HELPERS is set
> +
> +obj-y += arm_ffa_helper.o
> diff --git a/lib/arm-ffa/arm_ffa_helper.c b/lib/arm-ffa/arm_ffa_helper.c
> new file mode 100644
> index 0000000000..a291b000a7
> --- /dev/null
> +++ b/lib/arm-ffa/arm_ffa_helper.c
> @@ -0,0 +1,188 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include <common.h>
> +#include <arm_ffa_helper.h>
> +#include <uuid.h>
> +
> +/**
> + * ffa_helper_get_partitions_info - Wrapper function for FFA_PARTITION_INFO_GET
> + *
> + * @func_data: Pointer to the FF-A function arguments container
> + *				structure.
> + *				The passed arguments:
> + *					Mode 1: When getting from the driver the number of
> + *						secure partitions:
> + *						@data0_size: UUID size
> + *						@data0: pointer to the UUID (little endian)
> + *						@data1_size: size of the number of partitions
> + *									variable
> + *						@data1: pointer to the number of partitions
> + *								 variable. The variable will be set
> + *								 by the driver
> + *					Mode 2: When requesting the driver to return the
> + *						partitions information:
> + *						@data0_size: UUID size
> + *						@data0: pointer to the UUID (little endian)
> + *						@data1_size: size of the SPs information buffer
> + *						@data1: pointer to SPs information buffer
> + *								(allocated by the client).
> + *							The buffer will be filled by the driver
> + *
> + * This is the boot time function used by clients who wants to get from secure
> + * world the partition(s) information.
> + *
> + * A client of the FF-A driver should know the UUID of the service it wants to
> + * access. It should use the UUID to request the FF-A driver to provide the
> + * partition(s) information of the service. The client should use
> + * ffa_helper_get_partitions_info to pass the UUID information to the driver
> + * which uses PARTITION_INFO_GET to obtain the partition(s) information.
> + *
> + * ffa_helper_get_partitions_info should be called twice. First call is to get
> + * from the driver the number of secure partitions (SPs) associated to a
> + * particular UUID. Then, the caller (client) allocates the buffer to host the
> + * SPs data and issues a 2nd call. Then, the driver fills the SPs data in the
> + * pre-allocated buffer.
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +int ffa_helper_get_partitions_info(struct ffa_interface_data *func_data)
> +{
> +	return ffa_get_invoke_func(FFA_PARTITION_INFO_GET, func_data);
> +}
> +
> +/**
> + * ffa_helper_unmap_rxtx_buffers - Wrapper function for FFA_RXTX_UNMAP
> + *
> + * This is the boot time function that allows clients to unmap the RX/TX
> + * buffers
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +int ffa_helper_unmap_rxtx_buffers(void)
> +{
> +	return ffa_get_invoke_func(FFA_RXTX_UNMAP, NULL);
> +}
> +
> +/**
> + * ffa_helper_msg_send_direct_req - Wrapper function for
> + *								FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * @func_data: Pointer to the FF-A function arguments container structure.
> + * The passed arguments:
> + *	@data0_size: partition ID size
> + *	@data0: pointer to the partition ID
> + *	@data1_size: exchanged data size
> + *	@data1: pointer to the data buffer preallocated by the client (in/out)
> + *
> + * This is the runtime function that allows clients to send data to the secure
> + * world partitions. The arm_ffa driver uses FFA_MSG_SEND_DIRECT_REQ to send the
> + * data to the secure partition. The response from the secure partition is
> + * handled internally by the driver using FFA_MSG_SEND_DIRECT_RESP and returned
> + * to ffa_helper_msg_send_direct_req through @func_data
> + *
> + * The maximum size of the data that can be exchanged is 20 bytes which is
> + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + *
> + * The client should pre-allocate a buffer pointed by @data1 which the size
> + * is sizeof(struct ffa_send_direct_data)
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data
> +											 *func_data)
> +{
> +	return ffa_get_invoke_func(FFA_MSG_SEND_DIRECT_REQ, func_data);
> +}
> +
> +/**
> + * ffa_helper_bus_discover - Wrapper function for FF-A bus discovery
> + *
> + * This boot time function should be called to discover the FF-A bus and
> + * probe the FF-A device.
> + * To achieve that, this function is called automatically at initcalls
> + * level (after u-boot relocation).
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +int ffa_helper_bus_discover(void)
> +{
> +	return ffa_bus_discover();
> +}
> +
> +/**
> + * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
> + * @uuid_str:	UUID string in big endian format (36 bytes wide + '/0')
> + * @uuid_bin:	preallocated 16 bytes UUID buffer in little endian format
> + *
> + * UUID binary format used by the FF-A framework (16 bytes):
> + *
> + * [LSB] 4B-2B-2B-2B-6B (little endian data fields)
> + *
> + * UUID string is 36 length of characters (36 bytes):
> + *
> + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
> + * be                be      be       be      be
> + *
> + * where x is a hexadecimal character. Fields are separated by '-'s.
> + * When converting to a binary UUID, these endianness rules apply:
> + *     be: means the field in the string is considered a big endian hex number
> + *         and should be converted to little endian binary format
> + *
> + * Return:
> + *
> + *    uuid_bin filled with little endian UUID data
> + *    On success 0 is returned. Otherwise, failure code.
> + */
> +int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin)
> +{
> +	u16 tmp16 = 0;
> +	u32 tmp32 = 0;
> +	u64 tmp64 = 0;
> +
> +	if (!uuid_str_valid(uuid_str) || !uuid_bin)
> +		return -EINVAL;
> +
> +	/*
> +	 * reverse bytes from big to little endian
> +	 */
> +	tmp32 = simple_strtoul(uuid_str, NULL, 16);
> +	memcpy(uuid_bin, &tmp32, 4);
> +
> +	/*
> +	 * reverse bytes from big to little endian
> +	 */
> +	tmp16 = simple_strtoul(uuid_str + 9, NULL, 16);
> +	memcpy(uuid_bin + 4, &tmp16, 2);
> +
> +	/*
> +	 * reverse bytes from big to little endian
> +	 */
> +	tmp16 = simple_strtoul(uuid_str + 14, NULL, 16);
> +	memcpy(uuid_bin + 6, &tmp16, 2);
> +
> +	/*
> +	 * reverse bytes from big to little endian
> +	 */
> +	tmp16 = simple_strtoul(uuid_str + 19, NULL, 16);
> +	memcpy(uuid_bin + 8, &tmp16, 2);
> +
> +	/*
> +	 * reverse bytes from big to little endian
> +	 */
> +	tmp64 = simple_strtoull(uuid_str + 24, NULL, 16);
> +	memcpy(uuid_bin + 10, (char *)&tmp64, 6);
> +
> +	return 0;
> +}
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index 5bcb8253ed..cffa2c69d6 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -23,6 +23,10 @@
>  #include <asm/setjmp.h>
>  #include <linux/libfdt_env.h>
>  
> +#if defined(CONFIG_ARM_FFA_TRANSPORT)
> +#include <arm_ffa_helper.h>
> +#endif
> +
>  DECLARE_GLOBAL_DATA_PTR;
>  
>  /* Task priority level */
> @@ -2114,6 +2118,10 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
>  	struct efi_event *evt, *next_event;
>  	efi_status_t ret = EFI_SUCCESS;
>  
> +#if defined(CONFIG_ARM_FFA_TRANSPORT)
> +	int ffa_ret;
> +#endif
> +
>  	EFI_ENTRY("%p, %zx", image_handle, map_key);
>  
>  	/* Check that the caller has read the current memory map */
> @@ -2174,6 +2182,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
>  		dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
>  	}
>  
> +#if defined(CONFIG_ARM_FFA_TRANSPORT)
> +	/* unmap FF-A RX/TX buffers */
> +	ffa_ret = ffa_helper_unmap_rxtx_buffers();
> +	if (ffa_ret)
> +		debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n");
> +	else
> +		debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
> +#endif
> +
>  	/* Patch out unsupported runtime function */
>  	efi_runtime_detach();
>  
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v3 0/4] introduce Arm FF-A support
  2022-05-12 14:43                           ` Ilias Apalodimas
@ 2022-08-01 17:20                             ` Abdellatif El Khlifi
  2022-08-01 17:20                               ` [PATCH v3 1/4] arm64: smccc: add Xn registers support used by SMC calls Abdellatif El Khlifi
                                                 ` (4 more replies)
  0 siblings, 5 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-08-01 17:20 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: jens.wiklander, abdellatif.elkhlifi, achin.gupta, trini, u-boot,
	vishnu.banavath, xueliang.zhong, nd, Xueliang Zhong

This new version of the patchset provides improvements to the FF-A driver design.

The FF-A driver is a discoverable bus and brings these new features:

* support for the 64-bit x0-x17 registers in SMC arguments passing 
* align with the FF-A kernel driver interfaces
* make the driver EFI independent

This patchset will be followed by further updates (work in progress):

* discover MM partitions at runtime
* align with the FF-A kernel driver error handling
* align Sandbox driver and tests with the new interfaces

Changelog:
===============

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/


Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Vishnu Banavath <vishnu.banavath@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (4):
  arm64: smccc: add Xn registers support used by SMC calls
  arm64: smccc: clear the Xn registers after SMC calls
  arm_ffa: introduce Arm FF-A low-level driver
  arm_ffa: introduce armffa command

 MAINTAINERS                                |    7 +
 arch/arm/cpu/armv8/smccc-call.S            |   73 ++
 arch/arm/lib/asm-offsets.c                 |   13 +
 cmd/Kconfig                                |   10 +
 cmd/Makefile                               |    2 +
 cmd/armffa.c                               |  246 ++++
 common/board_r.c                           |    7 +
 drivers/Kconfig                            |    2 +
 drivers/Makefile                           |    1 +
 drivers/arm-ffa/Kconfig                    |   34 +
 drivers/arm-ffa/Makefile                   |    7 +
 drivers/arm-ffa/arm-ffa-uclass.c           |   16 +
 drivers/arm-ffa/arm_ffa_prv.h              |  219 ++++
 drivers/arm-ffa/core.c                     | 1338 ++++++++++++++++++++
 drivers/arm-ffa/efi_ffa_runtime_data_mgr.c |   94 ++
 include/arm_ffa.h                          |  132 ++
 include/dm/uclass-id.h                     |    1 +
 include/linux/arm-smccc.h                  |   43 +
 include/uuid.h                             |    8 +
 lib/efi_loader/efi_boottime.c              |   17 +
 lib/uuid.c                                 |   65 +
 21 files changed, 2335 insertions(+)
 create mode 100644 cmd/armffa.c
 create mode 100644 drivers/arm-ffa/Kconfig
 create mode 100644 drivers/arm-ffa/Makefile
 create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/arm-ffa/core.c
 create mode 100644 drivers/arm-ffa/efi_ffa_runtime_data_mgr.c
 create mode 100644 include/arm_ffa.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v3 1/4] arm64: smccc: add Xn registers support used by SMC calls
  2022-08-01 17:20                             ` [PATCH v3 0/4] " Abdellatif El Khlifi
@ 2022-08-01 17:20                               ` Abdellatif El Khlifi
  2022-08-01 18:41                                 ` Sudeep Holla
  2022-08-01 17:20                               ` [PATCH v3 2/4] arm64: smccc: clear the Xn registers after " Abdellatif El Khlifi
                                                 ` (3 subsequent siblings)
  4 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-08-01 17:20 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: jens.wiklander, abdellatif.elkhlifi, achin.gupta, trini, u-boot,
	vishnu.banavath, xueliang.zhong, nd, Sudeep Holla

use x0-x17 registers in the SMC32/SMC64 calls according to SMCCCv1.2

Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
---
 arch/arm/cpu/armv8/smccc-call.S | 53 +++++++++++++++++++++++++++++++++
 arch/arm/lib/asm-offsets.c      | 13 ++++++++
 include/linux/arm-smccc.h       | 43 ++++++++++++++++++++++++++
 3 files changed, 109 insertions(+)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..ec6f299bc9 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
@@ -45,3 +47,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 22fd541f9a..b6bd1b32b0 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,8 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * (C) Copyright 2022 ARM Limited
  */
 
 #include <common.h>
@@ -117,6 +119,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+	#ifdef CONFIG_ARM64
+		DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+		DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+		DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+		DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+		DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+		DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+		DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+		DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+		DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+	#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..9105031d55 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +72,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v3 2/4] arm64: smccc: clear the Xn registers after SMC calls
  2022-08-01 17:20                             ` [PATCH v3 0/4] " Abdellatif El Khlifi
  2022-08-01 17:20                               ` [PATCH v3 1/4] arm64: smccc: add Xn registers support used by SMC calls Abdellatif El Khlifi
@ 2022-08-01 17:20                               ` Abdellatif El Khlifi
  2022-08-16 11:48                                 ` Jens Wiklander
  2022-08-01 17:20                               ` [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
                                                 ` (2 subsequent siblings)
  4 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-08-01 17:20 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: jens.wiklander, abdellatif.elkhlifi, achin.gupta, trini, u-boot,
	vishnu.banavath, xueliang.zhong, nd

set to zero the x0-x17 registers

As per the SMCCC v1.2 spec, unused result and scratch registers can leak
information after an SMC call. We can mitigate against this risk by
returning zero in each register.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
---
 arch/arm/cpu/armv8/smccc-call.S | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index ec6f299bc9..8ac3e461e4 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -84,6 +84,26 @@ ENDPROC(__arm_smccc_hvc)
 	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
 	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
 
+	/* x0-x17 registers can leak information after an SMC or HVC call. Let's clear them */
+	mov	x0, xzr
+	mov	x1, xzr
+	mov	x2, xzr
+	mov	x3, xzr
+	mov	x4, xzr
+	mov	x5, xzr
+	mov	x6, xzr
+	mov	x7, xzr
+	mov	x8, xzr
+	mov	x9, xzr
+	mov	x10, xzr
+	mov	x11, xzr
+	mov	x12, xzr
+	mov	x13, xzr
+	mov	x14, xzr
+	mov	x15, xzr
+	mov	x16, xzr
+	mov	x17, xzr
+
 	/* Restore original x19 */
 	ldp     xzr, x19, [sp], #16
 	ret
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver
  2022-08-01 17:20                             ` [PATCH v3 0/4] " Abdellatif El Khlifi
  2022-08-01 17:20                               ` [PATCH v3 1/4] arm64: smccc: add Xn registers support used by SMC calls Abdellatif El Khlifi
  2022-08-01 17:20                               ` [PATCH v3 2/4] arm64: smccc: clear the Xn registers after " Abdellatif El Khlifi
@ 2022-08-01 17:20                               ` Abdellatif El Khlifi
  2022-08-12  7:39                                 ` Ilias Apalodimas
                                                   ` (2 more replies)
  2022-08-01 17:20                               ` [PATCH v3 4/4] arm_ffa: introduce armffa command Abdellatif El Khlifi
  2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  4 siblings, 3 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-08-01 17:20 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: jens.wiklander, abdellatif.elkhlifi, achin.gupta, trini, u-boot,
	vishnu.banavath, xueliang.zhong, nd

Add the driver implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A)
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
and FFA_MSG_SEND_DIRECT_{REQ, RESP}.

In u-boot FF-A design, FF-A is considered as a discoverable bus.
The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- partition_info_get
- sync_send_receive
- rxtx_unmap

This implementation provides an optional feature to copy the driver data
to EFI runtime area.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
---
 MAINTAINERS                                |    6 +
 common/board_r.c                           |    7 +
 drivers/Kconfig                            |    2 +
 drivers/Makefile                           |    1 +
 drivers/arm-ffa/Kconfig                    |   33 +
 drivers/arm-ffa/Makefile                   |    7 +
 drivers/arm-ffa/arm-ffa-uclass.c           |   16 +
 drivers/arm-ffa/arm_ffa_prv.h              |  219 ++++
 drivers/arm-ffa/core.c                     | 1338 ++++++++++++++++++++
 drivers/arm-ffa/efi_ffa_runtime_data_mgr.c |   94 ++
 include/arm_ffa.h                          |  132 ++
 include/dm/uclass-id.h                     |    1 +
 include/uuid.h                             |    8 +
 lib/efi_loader/efi_boottime.c              |   17 +
 lib/uuid.c                                 |   65 +
 15 files changed, 1946 insertions(+)
 create mode 100644 drivers/arm-ffa/Kconfig
 create mode 100644 drivers/arm-ffa/Makefile
 create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/arm-ffa/core.c
 create mode 100644 drivers/arm-ffa/efi_ffa_runtime_data_mgr.c
 create mode 100644 include/arm_ffa.h

diff --git a/MAINTAINERS b/MAINTAINERS
index f371d864f2..93a57f4df2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -248,6 +248,12 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	drivers/arm-ffa/
+F:	include/arm_ffa.h
+
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/common/board_r.c b/common/board_r.c
index ed29069d2d..2d3f359b96 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -63,6 +63,10 @@
 #include <efi_loader.h>
 #include <relocate.h>
 
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+#include <arm_ffa.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -767,6 +771,9 @@ static init_fnc_t init_sequence_r[] = {
 	INIT_FUNC_WATCHDOG_RESET
 	initr_net,
 #endif
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+	ffa_bus_discover,
+#endif
 #ifdef CONFIG_POST
 	initr_post,
 #endif
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 8b6fead351..60b5fd4d9d 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
 
 source "drivers/adc/Kconfig"
 
+source "drivers/arm-ffa/Kconfig"
+
 source "drivers/ata/Kconfig"
 
 source "drivers/axi/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index eba9940231..dfde371381 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -110,6 +110,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
new file mode 100644
index 0000000000..882ffde90f
--- /dev/null
+++ b/drivers/arm-ffa/Kconfig
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  This driver is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In u-boot FF-A design, FF-A is considered as a discoverable bus.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  This FF-A driver takes care of all the interactions between Normal world
+	  and Secure World.
+
+config ARM_FFA_EFI_RUNTIME_MODE
+	bool "Enable EFI runtime support for FF-A data and code "
+	depends on ARM_FFA_TRANSPORT && EFI_LOADER
+	help
+	  Allows FF-A driver data structures and code to be accessible at EFI runtime
diff --git a/drivers/arm-ffa/Makefile b/drivers/arm-ffa/Makefile
new file mode 100644
index 0000000000..0b9b0a61b4
--- /dev/null
+++ b/drivers/arm-ffa/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+#
+
+obj-y += arm-ffa-uclass.o core.o
+obj-$(CONFIG_ARM_FFA_EFI_RUNTIME_MODE) += efi_ffa_runtime_data_mgr.o
diff --git a/drivers/arm-ffa/arm-ffa-uclass.c b/drivers/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..7d9695d289
--- /dev/null
+++ b/drivers/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+UCLASS_DRIVER(ffa) = {
+	.name		= "ffa",
+	.id		= UCLASS_FFA,
+};
diff --git a/drivers/arm-ffa/arm_ffa_prv.h b/drivers/arm-ffa/arm_ffa_prv.h
new file mode 100644
index 0000000000..1133c02400
--- /dev/null
+++ b/drivers/arm-ffa/arm_ffa_prv.h
@@ -0,0 +1,219 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <arm_ffa.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/arm-smccc.h>
+
+/*
+ * This header is private. It is exclusively used by the FF-A driver
+ */
+
+/* FF-A core driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* FF-A driver version definitions */
+
+#define MAJOR_VERSION_MASK		GENMASK(30, 16)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/*
+ * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
+ */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+#define FFA_VERSION				FFA_SMC_32(0x63)
+#define FFA_ID_GET				FFA_SMC_32(0x69)
+#define FFA_FEATURES				FFA_SMC_32(0x64)
+#define FFA_PARTITION_INFO_GET			FFA_SMC_32(0x68)
+#define FFA_RXTX_UNMAP				FFA_SMC_32(0x67)
+#define FFA_RX_RELEASE				FFA_SMC_32(0x65)
+#define FFA_RUN					FFA_SMC_32(0x6D)
+#define FFA_ERROR				FFA_SMC_32(0x60)
+#define FFA_SUCCESS				FFA_SMC_32(0x61)
+#define FFA_INTERRUPT				FFA_SMC_32(0x62)
+#define FFA_RXTX_MAP				FFA_SMC_64(0x66)
+#define FFA_MSG_SEND_DIRECT_REQ			FFA_SMC_64(0x6F)
+#define FFA_MSG_SEND_DIRECT_RESP		FFA_SMC_64(0x70)
+
+/* 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);
+
+/* FF-A error codes */
+#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_INTERRUPTED				(-5)
+#define FFA_ERR_STAT_DENIED				(-6)
+#define FFA_ERR_STAT_RETRY				(-7)
+#define FFA_ERR_STAT_ABORTED				(-8)
+
+/* UUID data size */
+#define UUID_SIZE (16)
+
+/*
+ * union ffa_partition_uuid - Data union hosting the UUID
+ *							transmitted by FFA_PARTITION_INFO_GET
+ * @words:	data structure giving 32-bit words access to the UUID data
+ * @bytes:	data structure giving byte access to the UUID data
+ *
+ * The structure holds little-endian UUID data.
+ */
+union ffa_partition_uuid {
+	struct __packed words {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+	} words;
+	u8 bytes[UUID_SIZE];
+};
+
+/**
+ * struct ffa_features_desc - FF-A functions features
+ * @func_id:	FF-A function
+ * @field1:	features read from register w2
+ * @field2:	features read from register w3
+ *
+ * Data structure describing the features of the  FF-A functions queried by
+ * FFA_FEATURES
+ */
+struct ffa_features_desc {
+	u32 func_id;
+	u32 field1;
+	u64 field2;
+};
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/*
+ * Number of the FF-A interfaces features descriptors
+ * currently only FFA_RXTX_MAP descriptor is supported
+ */
+#define FFA_FEATURE_DESC_CNT (1)
+
+/**
+ * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ *
+ * Data structure hosting the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	u64 rxbuf; /* virtual address */
+	u64 txbuf; /* virtual address */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @UUID:	UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	union ffa_partition_uuid UUID;
+};
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * This data structure contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* virtual address */
+};
+
+/**
+ * struct ffa_prvdata - the driver private data structure
+ *
+ * @dev:	The arm_ffa device under u-boot driver model
+ * @ffa_ops:	The driver operations structure
+ * @fwk_version:	FF-A framework version
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ * @invoke_ffa_fn:	The function executing the FF-A function
+ * @features:	Table of the FF-A functions having features
+ *
+ * The driver data structure hosting all resident data.
+ */
+struct ffa_prvdata {
+	struct udevice *dev;
+	struct ffa_bus_ops ffa_ops;
+	u32 fwk_version;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+	invoke_ffa_fn_t invoke_ffa_fn;
+	struct ffa_features_desc features[FFA_FEATURE_DESC_CNT];
+};
+
+/**
+ * ffa_device_get - create, bind and probe the arm_ffa device
+ */
+int ffa_device_get(void);
+
+/**
+ * ffa_bus_prvdata_get - bus driver private data getter
+ */
+struct ffa_prvdata **ffa_bus_prvdata_get(void);
+
+#endif
diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c
new file mode 100644
index 0000000000..40d140fc3e
--- /dev/null
+++ b/drivers/arm-ffa/core.c
@@ -0,0 +1,1338 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include "arm_ffa_prv.h"
+#include <asm/global_data.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * The device private data structure containing all the resident
+ * data read from secure world
+ */
+__ffa_runtime_data struct ffa_prvdata *ffa_priv_data;
+
+/*
+ * Driver functions
+ */
+
+/**
+ * ffa_remove_device - removes the arm_ffa device
+ * @dev:	the device to be removed
+ *
+ * This boot time function makes sure the arm_ffa device is removed
+ * No need to free the kmalloced data when the device is destroyed.
+ * It's automatically done by devm management.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int ffa_remove_device(struct udevice *dev)
+{
+	int ret;
+
+	if (!dev)
+		return -ENODEV;
+
+	ret = device_remove(dev, DM_REMOVE_NORMAL);
+	if (ret) {
+		ffa_err("Unable to remove. err:%d\n", ret);
+		return ret;
+	}
+
+	ret = device_unbind(dev);
+	if (ret) {
+		ffa_err("Unable to unbind. err:%d\n", ret);
+		return ret;
+	}
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_device_get - create, bind and probe the arm_ffa device
+ *
+ * This boot time function makes sure the arm_ffa device is
+ * created, bound to this driver, probed and ready to use.
+ * Arm FF-A transport is implemented through a single u-boot
+ * device managing the FF-A bus (arm_ffa).
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int ffa_device_get(void)
+{
+	int ret;
+	struct udevice *dev = NULL;
+
+	if (ffa_priv_data && ffa_priv_data->dev)
+		return FFA_ERR_STAT_SUCCESS;
+
+	ret = device_bind(dm_root(),
+			  DM_DRIVER_GET(arm_ffa),
+			  FFA_DRV_NAME,
+			  NULL,
+			  ofnode_null(),
+			  &dev);
+	if (ret)
+		return ret;
+
+	/* The FF-A bus discovery succeeds when probing is successful */
+	ret = device_probe(dev);
+	if (ret) {
+		ffa_err("arm_ffa device probing failed");
+		ffa_remove_device(dev);
+		return ret;
+	}
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_get_version - FFA_VERSION handler function
+ *
+ * This is the boot time function that implements FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_get_version(void)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+
+	if (!ffa_priv_data->invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_VERSION,
+			.a1 = FFA_VERSION_1_0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	if (((int)res.a0) == FFA_ERR_STAT_NOT_SUPPORTED) {
+		ffa_err("A Firmware Framework implementation does not exist");
+		return -EOPNOTSUPP;
+	}
+
+	major = GET_FFA_MAJOR_VERSION((u32)res.a0);
+	minor = GET_FFA_MINOR_VERSION((u32)res.a0);
+
+	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
+		ffa_info("Versions are compatible ");
+
+		ffa_priv_data->fwk_version = (u32)res.a0;
+
+		return FFA_ERR_STAT_SUCCESS;
+	}
+
+	ffa_err("Versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id - FFA_ID_GET handler function
+ *
+ * This is the boot time function that implements FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(void)
+{
+	ffa_value_t res = {0};
+
+	if (!ffa_priv_data->invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_ID_GET,
+			.a1 = 0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+
+		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
+			ffa_err("This function is not implemented at this FF-A instance");
+			return -EOPNOTSUPP;
+		}
+
+		ffa_err("Undefined error code (%d)", ((int)res.a2));
+		return -EINVAL;
+
+	case FFA_SUCCESS:
+
+		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		ffa_info("endpoint ID is %u", ffa_priv_data->id);
+
+		return FFA_ERR_STAT_SUCCESS;
+
+	default:
+
+		ffa_err("Undefined response function (0x%lx)", res.a0);
+		return -EINVAL;
+	}
+}
+
+/**
+ * ffa_get_features_desc - returns the features descriptor of the specified
+ *						FF-A function
+ * @func_id:	the FF-A function which the features are to be retrieved
+ *
+ * This is a boot time function that searches the features descriptor of the
+ * specified FF-A function
+ *
+ * Return:
+ *
+ * When found, the address of the features descriptor is returned. Otherwise, NULL.
+ */
+static struct ffa_features_desc *ffa_get_features_desc(u32 func_id)
+{
+	u32 desc_idx;
+
+	/*
+	 * search for the descriptor of the selected FF-A interface
+	 */
+	for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
+		if (ffa_priv_data->features[desc_idx].func_id == func_id)
+			return &ffa_priv_data->features[desc_idx];
+
+	return NULL;
+}
+
+/**
+ * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP
+ *							argument
+ *
+ * This is the boot time function that implements FFA_FEATURES FF-A function
+ * to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features(void)
+{
+	ffa_value_t res = {0};
+
+	if (!ffa_priv_data->invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_FEATURES,
+			.a1 = FFA_RXTX_MAP,
+			.a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
+			ffa_err("FFA_RXTX_MAP is not implemented at this FF-A instance");
+			return -EOPNOTSUPP;
+		}
+
+		ffa_err("Undefined error code (%d)", ((int)res.a2));
+		return -EINVAL;
+	}
+	case FFA_SUCCESS:
+	{
+		u32 desc_idx;
+
+		/*
+		 * search for an empty descriptor
+		 */
+		for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
+			if (!ffa_priv_data->features[desc_idx].func_id) {
+				/*
+				 * populate the descriptor with
+				 * the interface features data
+				 */
+				ffa_priv_data->features[desc_idx].func_id =
+					FFA_RXTX_MAP;
+				ffa_priv_data->features[desc_idx].field1 =
+					(u32)res.a2;
+
+				ffa_info("FFA_RXTX_MAP features data 0x%x",
+					 ffa_priv_data->features[desc_idx].field1);
+
+				return FFA_ERR_STAT_SUCCESS;
+			}
+
+		ffa_err("Cannot save FFA_RXTX_MAP features data. Descriptors table full");
+		return -ENOBUFS;
+	}
+	default:
+	{
+		ffa_err("Undefined response function (0x%lx)",
+			res.a0);
+		return -EINVAL;
+	}
+	}
+}
+
+/**
+ * ffa_get_rxtx_buffers_pages_cnt - reads from the features data descriptors
+ *						the minimum number of pages in each of the RX/TX
+ *						buffers
+ * @buf_4k_pages: Pointer to the minimum number of pages
+ *
+ * This is the boot time function that  returns the minimum number of pages
+ *  in each of the RX/TX buffers
+ *
+ * Return:
+ *
+ * buf_4k_pages points to the returned number of pages
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_buffers_pages_cnt(size_t *buf_4k_pages)
+{
+	struct ffa_features_desc *desc = NULL;
+
+	if (!buf_4k_pages)
+		return -EINVAL;
+
+	desc = ffa_get_features_desc(FFA_RXTX_MAP);
+	if (!desc)
+		return -EINVAL;
+
+	switch (desc->field1) {
+	case RXTX_4K:
+		*buf_4k_pages = 1;
+		break;
+	case RXTX_16K:
+		*buf_4k_pages = 4;
+		break;
+	case RXTX_64K:
+		*buf_4k_pages = 16;
+		break;
+	default:
+		ffa_err("RX/TX buffer size not supported");
+		return -EINVAL;
+	}
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_free_rxtx_buffers - frees the RX/TX buffers
+ * @buf_4k_pages: the minimum number of pages in each of the RX/TX
+ *			  buffers
+ *
+ * This is the boot time function used to free the RX/TX buffers
+ *
+ */
+static void ffa_free_rxtx_buffers(void)
+{
+	ffa_info("Freeing RX/TX buffers");
+
+	if (ffa_priv_data->pair.rxbuf) {
+		free((void *)ffa_priv_data->pair.rxbuf);
+		ffa_priv_data->pair.rxbuf = 0;
+	}
+
+	if (ffa_priv_data->pair.txbuf) {
+		free((void *)ffa_priv_data->pair.txbuf);
+		ffa_priv_data->pair.txbuf = 0;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
+ * @buf_4k_pages: the minimum number of pages in each of the RX/TX
+ *			  buffers
+ *
+ * This is the boot time function used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(size_t buf_4k_pages)
+{
+	u64 bytes;
+
+	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size", buf_4k_pages);
+
+	bytes = buf_4k_pages * SZ_4K;
+
+	/* RX/TX buffers addresses should be PAGE_SIZE aligned */
+
+	ffa_priv_data->pair.rxbuf = (u64)memalign(PAGE_SIZE, bytes);
+	if (!ffa_priv_data->pair.rxbuf) {
+		ffa_err("Failure to allocate RX buffer");
+		return -ENOBUFS;
+	}
+
+	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
+
+	ffa_priv_data->pair.txbuf = (u64)memalign(PAGE_SIZE, bytes);
+	if (!ffa_priv_data->pair.txbuf) {
+		free((void *)ffa_priv_data->pair.rxbuf);
+		ffa_priv_data->pair.rxbuf = 0;
+		ffa_err("Failure to allocate the TX buffer");
+		return -ENOBUFS;
+	}
+
+	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
+
+	/*
+	 * make sure the buffers are cleared before use
+	 */
+	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
+	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
+ * @buf_4k_pages: the minimum number of pages in each of the RX/TX
+ *			  buffers
+ *
+ * This is the boot time function that implements FFA_RXTX_MAP FF-A function
+ * to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers(size_t buf_4k_pages)
+{
+	int ret;
+	ffa_value_t res = {0};
+
+	if (!ffa_priv_data->invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	ret = ffa_alloc_rxtx_buffers(buf_4k_pages);
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 *no need to convert from virtual to physical
+	 */
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_RXTX_MAP,
+			.a1 = ffa_priv_data->pair.txbuf,
+			.a2 = ffa_priv_data->pair.rxbuf,
+			.a3 = buf_4k_pages,
+			.a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		switch (((int)res.a2)) {
+		case FFA_ERR_STAT_INVALID_PARAMETERS:
+			ffa_err("One or more fields in input parameters is incorrectly encoded");
+			ret = -EPERM;
+			break;
+		case FFA_ERR_STAT_NO_MEMORY:
+			ffa_err("Not enough memory");
+			ret = -ENOMEM;
+			break;
+		case FFA_ERR_STAT_DENIED:
+			ffa_err("Buffer pair already registered");
+			ret = -EACCES;
+			break;
+		case FFA_ERR_STAT_NOT_SUPPORTED:
+			ffa_err("This function is not implemented at this FF-A instance");
+			ret = -EOPNOTSUPP;
+			break;
+		default:
+			ffa_err("Undefined error (%d)",
+				((int)res.a2));
+			ret = -EINVAL;
+		}
+		break;
+	}
+	case FFA_SUCCESS:
+		ffa_info("RX/TX buffers mapped");
+		return FFA_ERR_STAT_SUCCESS;
+	default:
+		ffa_err("Undefined response function (0x%lx)",
+			res.a0);
+		ret = -EINVAL;
+	}
+
+	ffa_free_rxtx_buffers();
+
+	return ret;
+}
+
+/**
+ * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
+ *
+ * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_unmap_rxtx_buffers(void)
+{
+	ffa_value_t res = {0};
+
+	if (!ffa_priv_data->invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_RXTX_UNMAP,
+			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id),
+			.a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
+			panic("[FFA] FFA_RXTX_UNMAP is not implemented at this FF-A instance\n");
+		else if (((int)res.a2) == FFA_ERR_STAT_INVALID_PARAMETERS)
+			panic("[FFA] There is no buffer pair registered on behalf of the caller\n");
+		else
+			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
+	}
+	case FFA_SUCCESS:
+	{
+		ffa_free_rxtx_buffers();
+
+		return FFA_ERR_STAT_SUCCESS;
+	}
+	default:
+		panic("[FFA] Undefined response function (0x%lx)", res.a0);
+		return -ENODEV;
+	}
+}
+
+/**
+ * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
+ *
+ * This is the boot time function that invokes FFA_RX_RELEASE FF-A function
+ * to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer(void)
+{
+	ffa_value_t res = {0};
+
+	if (!ffa_priv_data->invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_RX_RELEASE,
+			.a1 = 0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
+			panic("[FFA] FFA_RX_RELEASE is not implemented at this FF-A instance\n");
+		else if (((int)res.a2) == FFA_ERR_STAT_DENIED)
+			panic("[FFA] Caller did not have ownership of the RX buffer\n");
+		else
+			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
+	}
+	case FFA_SUCCESS:
+		return FFA_ERR_STAT_SUCCESS;
+
+	default:
+		panic("[FFA] Undefined response function (0x%lx)\n", res.a0);
+		return -ENODEV;
+	}
+}
+
+/**
+ * ffa_uuid_are_identical - checks whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * This is a boot time function used by ffa_read_partitions_info to search
+ * for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+int ffa_uuid_are_identical(const union ffa_partition_uuid *uuid1,
+			   const union ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return (!memcmp(uuid1, uuid2, sizeof(union ffa_partition_uuid)));
+}
+
+/**
+ * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
+ *							and saves it in the private structure
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * This is the boot time function that reads the partitions information
+ * returned by the FFA_PARTITION_INFO_GET and saves it in the private
+ * data structure.
+ *
+ * Return:
+ *
+ * The private data structure is updated with the partition(s) information
+ * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(u32 count, union ffa_partition_uuid *part_uuid)
+{
+	if (!count) {
+		ffa_err("No partition detected");
+		return -ENODATA;
+	}
+
+	ffa_info("Reading partitions data from the RX buffer");
+
+	if (!part_uuid) {
+		/*
+		 * querying information of all partitions
+		 */
+		u64 buf_bytes;
+		u64 data_bytes;
+		size_t buf_4k_pages = 0;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+		int ret;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		/*
+		 * get the RX buffer size in pages
+		 */
+		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
+		if (ret != FFA_ERR_STAT_SUCCESS) {
+			ffa_err("Can not get the RX buffer size (error %d)", ret);
+			return ret;
+		}
+
+		buf_bytes = buf_4k_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			ffa_err("Partitions data size exceeds the RX buffer size:");
+			ffa_err("    Sizes in bytes: data %llu , RX buffer %llu ",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		ffa_priv_data->partitions.descs = (struct ffa_partition_desc *)
+			devm_kmalloc(ffa_priv_data->dev, data_bytes, __GFP_ZERO);
+		if (!ffa_priv_data->partitions.descs) {
+			ffa_err("Cannot  allocate partitions data buffer");
+			return -ENOMEM;
+		}
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			ffa_priv_data->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			ffa_info("Partition ID %x : info cached",
+				 ffa_priv_data->partitions.descs[desc_idx].info.id);
+		}
+
+		ffa_priv_data->partitions.count = count;
+
+		ffa_info("%d partition(s) found and cached", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
+
+		/*
+		 * search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/*
+			 * search the current ID in the cached partitions
+			 */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < ffa_priv_data->partitions.count;
+			     cached_desc_idx++) {
+				/*
+				 * save the UUID
+				 */
+				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					ffa_priv_data->partitions.descs[cached_desc_idx].UUID =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
+ *
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * This is the boot time function that executes the FFA_PARTITION_INFO_GET
+ * to query the partitions data. Then, it calls ffa_read_partitions_info
+ * to save the data in the private data structure.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(union ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	union ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+
+	if (!ffa_priv_data->invoke_ffa_fn)
+		panic("[FFA] no private data found\n");
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	}
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_PARTITION_INFO_GET,
+			.a1 = query_uuid.words.a1,
+			.a2 = query_uuid.words.a2,
+			.a3 = query_uuid.words.a3,
+			.a4 = query_uuid.words.a4,
+			.a5 = 0,
+			.a6 = 0,
+			.a7 = 0,
+			}, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		switch (((int)res.a2)) {
+		case FFA_ERR_STAT_INVALID_PARAMETERS:
+			ffa_err("Unrecognized UUID");
+			return -EPERM;
+		case FFA_ERR_STAT_NO_MEMORY:
+			ffa_err("Results cannot fit in RX buffer of the caller");
+			return -ENOMEM;
+		case FFA_ERR_STAT_DENIED:
+			ffa_err("Callee is not in a state to handle this request");
+			return -EACCES;
+		case FFA_ERR_STAT_NOT_SUPPORTED:
+			ffa_err("This function is not implemented at this FF-A instance");
+			return -EOPNOTSUPP;
+		case FFA_ERR_STAT_BUSY:
+			ffa_err("RX buffer of the caller is not free");
+			return -EBUSY;
+		default:
+			ffa_err("Undefined error (%d)", ((int)res.a2));
+			return -EINVAL;
+		}
+	}
+	case FFA_SUCCESS:
+	{
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
+			if (ret)
+				ffa_err("Failed to read partition(s) data , error (%d)", ret);
+		}
+
+		/*
+		 * return the SP count
+		 */
+		if (part_uuid) {
+			if (!ret)
+				*pcount = (u32)res.a2;
+			else
+				*pcount = 0;
+		}
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer();
+
+		if (!part_uuid && !res.a2) {
+			ffa_err("[FFA] no partition installed in the system");
+			return -ENODEV;
+		}
+
+		return ret;
+	}
+	default:
+		ffa_err("Undefined response function (0x%lx)", res.a0);
+		return  -EINVAL;
+	}
+}
+
+/**
+ * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
+ *
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@uuid_str: pointer to the UUID string
+ *	@parts_size: pointer to the variable that contains the number of partitions
+ *			 The variable will be set by the driver
+ *	@buffer: NULL
+ *
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@uuid_str: pointer to the UUID string
+ *	@parts_size: pointer to the size of the SPs information buffer in bytes
+ *	@buffer: pointer to SPs information buffer
+ *		(allocated by the client).
+ *		The buffer will be filled by the driver
+ *
+ * This is the boot time function that queries the secure partition data from
+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * When invoked through a client request, ffa_get_partitions_info should be
+ * called twice. First call is to get from the driver the number of secure
+ * partitions (SPs) associated to a particular UUID.
+ * Then, the caller (client) allocates the buffer to host the SPs data and
+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
+ * buffer.
+ *
+ * To achieve the mechanism described above, ffa_get_partitions_info uses the
+ * following functions:
+ *		ffa_read_partitions_info
+ *		ffa_query_partitions_info
+ *
+ * Return:
+ *
+ * @parts_size: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer size, the buffer will be
+ * filled by the driver.
+ *
+ * On success FFA_ERR_STAT_SUCCESS is returned. Otherwise, failure
+ */
+static int ffa_get_partitions_info(const char *uuid_str,
+				   u32 *parts_size, struct ffa_partition_info *buffer)
+{
+	/*
+	 * fill_data:
+	 * 0: return the SP count
+	 * 1: fill SP data and return it to the caller
+	 * -1: undefined mode
+	 */
+	int fill_data = -1;
+	u32 desc_idx, client_desc_idx;
+	union ffa_partition_uuid part_uuid = {0};
+	u32 client_desc_max_cnt;
+	u32 parts_found = 0;
+
+	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
+		panic("[FFA] No partition installed\n");
+
+	if (!uuid_str) {
+		ffa_err("No UUID provided");
+		return -EINVAL;
+	}
+
+	if (!parts_size) {
+		ffa_err("No size/count provided");
+		return -EINVAL;
+	}
+
+	if (ffa_uuid_str_to_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		ffa_err("Invalid UUID");
+		return -EINVAL;
+	}
+
+	if (!buffer) {
+		/* Mode 1: getting the number of secure partitions */
+
+		fill_data = 0;
+
+		ffa_info("Preparing for checking partitions count");
+
+	} else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
+		   !(*parts_size % sizeof(struct ffa_partition_info))) {
+		/* Mode 2: retrieving the partitions information */
+
+		fill_data = 1;
+
+		client_desc_idx = 0;
+
+		/*
+		 * number of empty descriptors preallocated by the caller
+		 */
+		client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
+
+		ffa_info("Preparing for filling partitions info");
+
+	} else {
+		ffa_err("Invalid function arguments provided");
+		return -EINVAL;
+	}
+
+	ffa_info("Searching partitions using the provided UUID");
+
+	/*
+	 * search in the cached partitions
+	 */
+	for (desc_idx = 0;
+	     desc_idx < ffa_priv_data->partitions.count;
+	     desc_idx++) {
+		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].UUID,
+					   &part_uuid)) {
+			ffa_info("Partition ID %x matches the provided UUID",
+				 ffa_priv_data->partitions.descs[desc_idx].info.id);
+
+			parts_found++;
+
+			if (fill_data) {
+				/*
+				 * trying to fill the partition info in the input buffer
+				 */
+
+				if (client_desc_idx < client_desc_max_cnt) {
+					buffer[client_desc_idx++] =
+						ffa_priv_data->partitions.descs[desc_idx].info;
+					continue;
+				}
+
+				ffa_err("Failed to fill the current descriptor client buffer full");
+				return -ENOBUFS;
+			}
+		}
+	}
+
+	if (!parts_found) {
+		int ret;
+
+		ffa_info("No partition found. Querying framework ...");
+
+		ret = ffa_query_partitions_info(&part_uuid, &parts_found);
+
+		if (ret == FFA_ERR_STAT_SUCCESS) {
+			if (!fill_data) {
+				*parts_size = parts_found;
+
+				ffa_info("Number of partition(s) found matching the UUID: %d",
+					 parts_found);
+			} else {
+				/*
+				 * If SPs data detected, they are already in the private data
+				 * structure, retry searching SP data again to return them
+				 *  to the caller
+				 */
+				if (parts_found)
+					ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
+				else
+					ret = -ENODATA;
+			}
+		}
+
+		return ret;
+	}
+
+	/* partition(s) found */
+	if (!fill_data)
+		*parts_size = parts_found;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_cache_partitions_info - Queries and saves all secure partitions data
+ *
+ * This is a boot time function that invokes FFA_PARTITION_INFO_GET FF-A
+ * function to query from secure world all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in the
+ * resident private data structure and we keep the UUID field empty
+ * (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * This function is called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(void)
+{
+	return ffa_query_partitions_info(NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ *
+ * This is the runtime function that implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int __ffa_runtime ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg)
+{
+	ffa_value_t res = {0};
+
+	if (!ffa_priv_data->invoke_ffa_fn)
+		return -ENODEV;
+
+	/* No partition installed */
+	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
+		return -ENODEV;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_MSG_SEND_DIRECT_REQ,
+			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_INTERRUPT)
+		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_RUN,
+			.a1 = res.a1, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	switch (res.a0) {
+	case FFA_ERROR:
+	{
+		switch (((int)res.a2)) {
+		case FFA_ERR_STAT_INVALID_PARAMETERS:
+			/* Invalid endpoint ID or non-zero reserved register */
+			return -EPERM;
+		case FFA_ERR_STAT_ABORTED:
+			/* Message target ran into unexpected error and has aborted */
+			return -ECONNABORTED;
+		case FFA_ERR_STAT_DENIED:
+			/* Callee is not in a state to handle this request */
+			return -EACCES;
+		case FFA_ERR_STAT_NOT_SUPPORTED:
+			/* This function is not implemented at this FF-A instance */
+			return -EOPNOTSUPP;
+		case FFA_ERR_STAT_BUSY:
+			/* Message target is busy */
+			return -EBUSY;
+		default:
+			/* Undefined error */
+			return -ENXIO;
+		}
+	}
+	case FFA_SUCCESS:
+
+		/* Message sent with no response */
+		return FFA_ERR_STAT_SUCCESS;
+
+	case FFA_MSG_SEND_DIRECT_RESP:
+		/*
+		 * Message sent with response
+		 * extract the return data
+		 */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return FFA_ERR_STAT_SUCCESS;
+
+	default:
+		/* Undefined response function */
+		return -ENOENT;
+	}
+}
+
+/**
+ * __arm_ffa_fn_smc - SMC wrapper
+ *
+ * Calls low level SMC function
+ *
+ * Return: void
+ */
+void __ffa_runtime __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * ffa_set_conduit - Set the conduit
+ *
+ * This boot time function clears the private data structure and sets the conduit
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_set_conduit(void)
+{
+	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
+
+	ffa_info("Conduit is SMC");
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_set_bus_ops - Set the bus driver operations
+ *
+ * Setting the driver callbacks.
+ *
+ */
+static void ffa_set_bus_ops(void)
+{
+	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
+	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
+	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
+}
+
+/**
+ * ffa_alloc_prvdata - allocate the driver main data structure
+ * @dev:	the arm_ffa device
+ *
+ * This boot time function creates the main data structure embedding all the driver data.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_alloc_prvdata(struct udevice *dev)
+{
+	if (!dev)
+		return -ENODEV;
+
+	/* The device is registered with the DM. Let's create the driver main data structure*/
+
+	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
+	if (!ffa_priv_data) {
+		ffa_err("can not allocate the driver main data structure");
+		return -ENOMEM;
+	}
+
+	ffa_priv_data->dev = dev;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_probe - The driver probe function
+ * @dev:	the arm_ffa device
+ *
+ * Probing is done at boot time and triggered by the uclass device discovery.
+ * At probe level the following actions are done:
+ *	- setting the conduit
+ *	- querying the FF-A framework version
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of the specified FF-A calls
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in the resident private data structure.
+ *
+ * The probe will fail if either FF-A framework is not detected or the
+ * FF-A requests are not behaving correctly. This ensures that the
+ * driver is not installed and its operations are not exported to the clients.
+ * However, once the driver is successfully probed and an FF-A anomaly is
+ * detected when clients invoke the driver operations, the driver cause
+ * u-boot to panic because the client would not know what to do in such conditions.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int ffa_probe(struct udevice *dev)
+{
+	int ret;
+	size_t buf_4k_pages = 0;
+
+	ret = ffa_alloc_prvdata(dev);
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ffa_set_bus_ops();
+
+	ret = ffa_set_conduit();
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_get_version();
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_get_endpoint_id();
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features();
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers(buf_4k_pages);
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return ret;
+
+	ret = ffa_cache_partitions_info();
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		ffa_free_rxtx_buffers();
+		return ret;
+	}
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * ffa_bus_ops_get - bus driver operations getter
+ *
+ * Return:
+ * This runtime function returns a pointer to the driver operations structure
+ */
+const struct ffa_bus_ops * __ffa_runtime ffa_bus_ops_get(void)
+{
+	return &ffa_priv_data->ffa_ops;
+}
+
+/**
+ * ffa_bus_prvdata_get - bus driver private data getter
+ *
+ * Return:
+ * This boot time function returns a pointer to the main private data structure
+ */
+struct ffa_prvdata **ffa_bus_prvdata_get(void)
+{
+	return &ffa_priv_data;
+}
+
+/**
+ * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
+ *
+ * This boot time function makes sure the FF-A bus is discoverable.
+ * Then, the arm_ffa device is probed and ready to use.
+ * This function is called automatically at initcalls
+ * level (after u-boot relocation).
+ *
+ * Arm FF-A transport is implemented through arm_ffa u-boot device managing the FF-A
+ * communication.
+ * All FF-A clients should use the arm_ffa device to use the FF-A transport.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int ffa_bus_discover(void)
+{
+	return ffa_device_get();
+}
+
+/**
+ * Declaring the arm_ffa driver under UCLASS_FFA
+ */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.probe		= ffa_probe,
+};
diff --git a/drivers/arm-ffa/efi_ffa_runtime_data_mgr.c b/drivers/arm-ffa/efi_ffa_runtime_data_mgr.c
new file mode 100644
index 0000000000..942601a7ba
--- /dev/null
+++ b/drivers/arm-ffa/efi_ffa_runtime_data_mgr.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include "arm_ffa_prv.h"
+
+/**
+ * ffa_copy_runtime_data - copy the private data structure  to the runtime area
+ *
+ * This boot time function copies the arm_ffa driver data structures including
+ *  partitions data to the EFI runtime data section.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+efi_status_t ffa_copy_runtime_data(void)
+{
+	efi_status_t efi_ret;
+	efi_uintn_t prvdata_pages;
+	efi_uintn_t descs_pages;
+	struct ffa_prvdata **prvdata = NULL; /* Pointer to the current structure */
+	struct ffa_prvdata *runtime_prvdata = NULL; /* Pointer to the structure runtime copy */
+	u64 runtime_descs = 0;
+
+	prvdata = ffa_bus_prvdata_get();
+
+	printf("INFO: EFI: FFA: prv data area at 0x%llx\n", (u64)prvdata);
+
+	/* allocate private data runtime area */
+
+	prvdata_pages = efi_size_in_pages(sizeof(struct ffa_prvdata));
+	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				     EFI_RUNTIME_SERVICES_DATA,
+				     prvdata_pages,
+				     (u64 *)&runtime_prvdata);
+
+	if (efi_ret != EFI_SUCCESS) {
+		printf("ERROR: EFI: FFA: allocating runtime data (err: 0x%lx, addr 0x%llx)\n",
+		       efi_ret, (u64)runtime_prvdata);
+
+		return efi_ret;
+	}
+
+	printf("INFO: EFI: FFA: runtime data area at 0x%llx\n", (u64)runtime_prvdata);
+
+	if (!runtime_prvdata)
+		return EFI_INVALID_PARAMETER;
+
+	/* allocate the partition data runtime area */
+
+	descs_pages = efi_size_in_pages((*prvdata)->partitions.count *
+					sizeof(struct ffa_partition_desc));
+	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				     EFI_RUNTIME_SERVICES_DATA,
+				     descs_pages,
+				     &runtime_descs);
+
+	if (efi_ret != EFI_SUCCESS) {
+		printf("ERROR: EFI: FFA: allocating runtime SPs data (err: 0x%lx, addr 0x%llx)\n",
+		       efi_ret, runtime_descs);
+
+		efi_free_pages((u64)runtime_prvdata, prvdata_pages);
+
+		return efi_ret;
+	}
+
+	printf("INFO: EFI: FFA: SPs runtime area at 0x%llx\n", (u64)runtime_descs);
+
+	if (!runtime_descs)
+		return EFI_INVALID_PARAMETER;
+
+	*runtime_prvdata = **prvdata;
+
+	runtime_prvdata->dev = NULL;
+	runtime_prvdata->ffa_ops.partition_info_get = NULL;
+	runtime_prvdata->ffa_ops.rxtx_unmap = NULL;
+	runtime_prvdata->partitions.descs = (struct ffa_partition_desc *)runtime_descs;
+	runtime_prvdata->pair.rxbuf = 0;
+	runtime_prvdata->pair.txbuf = 0;
+
+	/*
+	 * Update the private data structure pointer in the driver
+	 * no need to free the old structure. devm takes care of that
+	 */
+	*prvdata = runtime_prvdata;
+
+	printf("INFO: EFI: FFA: runtime prv data now at 0x%llx , SPs count %d\n",
+	       (u64)*prvdata, (*prvdata)->partitions.count);
+
+	return FFA_ERR_STAT_SUCCESS;
+}
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..ee9ce2d99d
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * Macros for displaying logs
+ */
+
+#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
+#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
+
+/*
+ * The driver operations success error code
+ */
+#define FFA_ERR_STAT_SUCCESS				(0)
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct  __packed ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct __packed ffa_send_direct_data {
+	unsigned long data0; /* w3/x3 */
+	unsigned long data1; /* w4/x4 */
+	unsigned long data2; /* w5/x5 */
+	unsigned long data3; /* w6/x6 */
+	unsigned long data4; /* w7/x7 */
+};
+
+#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
+
+#include <efi_loader.h>
+
+/*
+ *  __ffa_runtime - controls whether functions are
+ * available after calling the EFI ExitBootServices service.
+ * Functions tagged with these keywords are resident (available at boot time and
+ * at runtime)
+ */
+
+#define __ffa_runtime_data __efi_runtime_data
+#define __ffa_runtime __efi_runtime
+
+#else
+
+/*
+ *  The FF-A driver is independent from EFI
+ */
+
+#define __ffa_runtime_data
+#define __ffa_runtime
+
+#endif
+
+/**
+ * struct ffa_bus_ops - The driver operations structure
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(const char *uuid_str,
+				  u32 *parts_size, struct ffa_partition_info *buffer);
+	int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg);
+	int (*rxtx_unmap)(void);
+};
+
+/**
+ * The device driver and the Uclass driver public functions
+ */
+
+/**
+ * ffa_bus_ops_get - driver operations getter
+ */
+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
+ */
+int ffa_bus_discover(void);
+
+#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
+
+/**
+ * ffa_copy_runtime_data - copy the private data structure and the SPs data to the runtime area
+ */
+efi_status_t ffa_copy_runtime_data(void);
+
+#endif
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index a432e43871..6eebbe9c7d 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -55,6 +55,7 @@ enum uclass_id {
 	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
 	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..789f8e0f15 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -44,4 +44,12 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+/**
+ * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
+ */
+int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin);
+#endif
+
 #endif
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 4da64b5d29..e02bb445f5 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -23,6 +23,10 @@
 #include <asm/setjmp.h>
 #include <linux/libfdt_env.h>
 
+#if defined(CONFIG_ARM_FFA_TRANSPORT)
+#include <arm_ffa.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Task priority level */
@@ -2113,6 +2117,10 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 	struct efi_event *evt, *next_event;
 	efi_status_t ret = EFI_SUCCESS;
 
+#if defined(CONFIG_ARM_FFA_TRANSPORT)
+	int ffa_ret;
+#endif
+
 	EFI_ENTRY("%p, %zx", image_handle, map_key);
 
 	/* Check that the caller has read the current memory map */
@@ -2173,6 +2181,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 		dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
 	}
 
+#if defined(CONFIG_ARM_FFA_TRANSPORT)
+	/* unmap FF-A RX/TX buffers */
+	ffa_ret = ffa_bus_ops_get()->rxtx_unmap();
+	if (ffa_ret)
+		debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n");
+	else
+		debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
+#endif
+
 	/* Patch out unsupported runtime function */
 	efi_runtime_detach();
 
diff --git a/lib/uuid.c b/lib/uuid.c
index 284f8113ff..50b3e61d59 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * Copyright 2022 ARM Limited
  */
 
 #include <common.h>
@@ -342,6 +343,70 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+/**
+ * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
+ * @uuid_str:	UUID string in big endian format (36 bytes wide + '/0')
+ * @uuid_bin:	preallocated 16 bytes UUID buffer in little endian format
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ * be		     be	     be	      be      be
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a binary UUID, these endianness rules apply:
+ *     be: means the field in the string is considered a big endian hex number
+ *	   and should be converted to little endian binary format
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16 = 0;
+	u32 tmp32 = 0;
+	u64 tmp64 = 0;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp32 = simple_strtoul(uuid_str, NULL, 16);
+	memcpy(uuid_bin, &tmp32, 4);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 9, NULL, 16);
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 14, NULL, 16);
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 19, NULL, 16);
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp64 = simple_strtoull(uuid_str + 24, NULL, 16);
+	memcpy(uuid_bin + 10, (char *)&tmp64, 6);
+
+	return 0;
+}
+#endif
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v3 4/4] arm_ffa: introduce armffa command
  2022-08-01 17:20                             ` [PATCH v3 0/4] " Abdellatif El Khlifi
                                                 ` (2 preceding siblings ...)
  2022-08-01 17:20                               ` [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
@ 2022-08-01 17:20                               ` Abdellatif El Khlifi
  2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  4 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-08-01 17:20 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: jens.wiklander, abdellatif.elkhlifi, achin.gupta, trini, u-boot,
	vishnu.banavath, xueliang.zhong, nd

Provide armffa command showcasing the use of the FF-A driver

The armffa command allows to query secure partitions data from
the secure world and exchanging messages with the partitions.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
---
 MAINTAINERS             |   1 +
 cmd/Kconfig             |  10 ++
 cmd/Makefile            |   2 +
 cmd/armffa.c            | 246 ++++++++++++++++++++++++++++++++++++++++
 drivers/arm-ffa/Kconfig |   1 +
 5 files changed, 260 insertions(+)
 create mode 100644 cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 93a57f4df2..b0fbc027c2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -251,6 +251,7 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+F:	cmd/armffa.c
 F:	drivers/arm-ffa/
 F:	include/arm_ffa.h
 
diff --git a/cmd/Kconfig b/cmd/Kconfig
index a8260aa170..22f85188ff 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -902,6 +902,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the Arm FF-A driver
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index 5e43a1e022..e40f52f1e4 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,8 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
 obj-$(CONFIG_CMD_AES) += aes.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..cb8a3d40aa
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <arm_ffa.h>
+#include <asm/io.h>
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+
+/**
+ * do_ffa_get_singular_partition_info - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver partition_info_get operation
+ * to retrieve the data.
+ * The input UUID string is expected to be in big endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_get_singular_partition_info(struct cmd_tbl *cmdtp, int flag, int argc,
+					      char *const argv[])
+{
+	u32 count = 0, size = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	/* Mode 1: getting the number of secure partitions */
+	ret = ffa_bus_ops_get()->partition_info_get(argv[0], &count, NULL);
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		ffa_err("Failure in querying partitions count (error code: %d)", ret);
+		return ret;
+	}
+
+	if (!count) {
+		ffa_info("No secure partition found");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with ffa_partition_info structs
+	 */
+
+	ffa_info("Pre-allocating %d partition(s) info structures", count);
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	size = count * sizeof(struct ffa_partition_info);
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+
+	ret = ffa_bus_ops_get()->partition_info_get(argv[0], &size, parts_info);
+	if (ret != FFA_ERR_STAT_SUCCESS) {
+		ffa_err("Failure in querying partition(s) info (error code: %d)", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * SPs found , show the partition information
+	 */
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		ffa_info("Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x",
+			 parts_info[info_idx].id,
+			 parts_info[info_idx].exec_ctxt,
+			 parts_info[info_idx].properties);
+	}
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * do_ffa_msg_send_direct_req - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function sends data to the secure partition which the ID is provided
+ * as an argument. The function uses the arm_ffa driver sync_send_receive operation
+ * to send data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int  do_ffa_msg_send_direct_req(struct cmd_tbl *cmdtp, int flag, int argc,
+				char *const argv[])
+{
+	struct ffa_send_direct_data msg = {0};
+	u64 pattern = 0xaabbccddaabbccd0;
+	u16 part_id;
+	int ret;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	errno = 0;
+	part_id = strtoul(argv[0], NULL, 16);
+
+	if (errno) {
+		ffa_err("Invalid partition ID");
+		return -EINVAL;
+	}
+
+	/*
+	 * filling the message data
+	 */
+	msg.data0 = ++pattern;
+	msg.data1 = ++pattern;
+	msg.data2 = ++pattern;
+	msg.data3 = ++pattern;
+	msg.data4 = ++pattern;
+
+	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
+	if (ret == FFA_ERR_STAT_SUCCESS) {
+		u8 cnt;
+
+		ffa_info("SP response:\n[LSB]");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			ffa_info("0x%llx", ((u64 *)&msg)[cnt]);
+	} else {
+		ffa_err("Sending direct request error (%d)", ret);
+	}
+
+	return ret;
+}
+
+/**
+ *do_ffa_dev_list - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the devices belonging to the UCLASS_FFA
+ * class. Currently, one device is expected to show up: the arm_ffa device
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_dev_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev = NULL;
+	int i, ret;
+
+	ffa_info("arm_ffa uclass entries:");
+
+	for (i = 0, ret = uclass_first_device(UCLASS_FFA, &dev);
+	     dev;
+	     ret = uclass_next_device(&dev), i++) {
+		if (ret)
+			break;
+
+		ffa_info("entry %d - instance %08x, ops %08x, plat %08x",
+			 i,
+			 (u32)map_to_sysmem(dev),
+			 (u32)map_to_sysmem(dev->driver->ops),
+			 (u32)map_to_sysmem(dev_get_plat(dev)));
+	}
+
+	return cmd_process_error(cmdtp, ret);
+}
+
+static struct cmd_tbl armffa_commands[] = {
+	U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_get_singular_partition_info, "", ""),
+	U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_msg_send_direct_req, "", ""),
+	U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_dev_list, "", ""),
+};
+
+/**
+ * do_armffa - the armffa command main function
+ * @cmdtp:	Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function identifies which armffa subcommand to run.
+ * Then, it makes sure the arm_ffa device is probed and
+ * ready for use.
+ * Then, it runs the subcommand.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct cmd_tbl *armffa_cmd;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
+
+	argc -= 2;
+	argv += 2;
+
+	if (!armffa_cmd || argc > armffa_cmd->maxargs)
+		return CMD_RET_USAGE;
+
+	ret = ffa_bus_discover();
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		return cmd_process_error(cmdtp, ret);
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
+
+	return cmd_process_error(armffa_cmd, ret);
+}
+
+U_BOOT_CMD(armffa, 4, 1, do_armffa,
+	   "Arm FF-A operations test command",
+	   "getpart <partition UUID>\n"
+	   "	 - lists the partition(s) info\n"
+	   "ping <partition ID>\n"
+	   "	 - sends a data pattern to the specified partition\n"
+	   "devlist\n"
+	   "	 - displays the arm_ffa device info\n");
diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
index 882ffde90f..25816b479b 100644
--- a/drivers/arm-ffa/Kconfig
+++ b/drivers/arm-ffa/Kconfig
@@ -4,6 +4,7 @@ config ARM_FFA_TRANSPORT
 	bool "Enable Arm Firmware Framework for Armv8-A driver"
 	depends on DM && ARM64
 	select ARM_SMCCC
+	select CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v3 1/4] arm64: smccc: add Xn registers support used by SMC calls
  2022-08-01 17:20                               ` [PATCH v3 1/4] arm64: smccc: add Xn registers support used by SMC calls Abdellatif El Khlifi
@ 2022-08-01 18:41                                 ` Sudeep Holla
  2022-08-05 11:17                                   ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Sudeep Holla @ 2022-08-01 18:41 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: ilias.apalodimas, jens.wiklander, achin.gupta, trini, u-boot,
	vishnu.banavath, xueliang.zhong

On Mon, Aug 01, 2022 at 06:20:50PM +0100, Abdellatif El Khlifi wrote:
> use x0-x17 registers in the SMC32/SMC64 calls according to SMCCCv1.2
> 
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

Please drop my signed-off as I didn't. I am seeing this patch on the list
for the first time and AFAIK I haven't posted any previous version of the
patch that you are picking up.

IIUC, you are importing this code from the Linux kernel tree which I assume
is fine. You can just mention the same and must not add anyone's sign-off
without consulting them.

OTH, if you cherry-pick the commit as is and use it in u-boot tree(e.g.
DTS patches), then you can retain them. That is my understanding. Happy
to be corrected if my assumptions are not correct here.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-04-13 16:46               ` Tom Rini
  2022-04-13 17:29                 ` Sudeep Holla
@ 2022-08-01 19:13                 ` Simon Glass
  2022-08-01 19:28                   ` Sudeep Holla
  1 sibling, 1 reply; 478+ messages in thread
From: Simon Glass @ 2022-08-01 19:13 UTC (permalink / raw)
  To: Tom Rini
  Cc: Abdellatif El Khlifi, Rob Herring, Ilias Apalodimas, achin.gupta,
	Sudeep Holla, Rui Miguel Silva, vishnu.banavath, xueliang.zhong,
	U-Boot Mailing List, nd

Hi,

On Wed, 13 Apr 2022 at 10:46, Tom Rini <trini@konsulko.com> wrote:
>
> On Wed, Apr 13, 2022 at 03:20:23PM +0100, Abdellatif El Khlifi wrote:
> > On Tue, Apr 12, 2022 at 08:28:42AM -0500, Rob Herring wrote:
> > > On Tue, Apr 12, 2022 at 7:01 AM Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Tue, Apr 12, 2022 at 12:43:15PM +0100, Abdellatif El Khlifi wrote:
> > > > > On Thu, Apr 07, 2022 at 08:58:11AM -0400, Tom Rini wrote:
> > > > > > On Thu, Apr 07, 2022 at 01:54:24PM +0100, Abdellatif El Khlifi wrote:
> > > > > > > On Wed, Apr 06, 2022 at 03:47:11PM -0400, Tom Rini wrote:
> > > > > > > > On Tue, Mar 29, 2022 at 04:16:53PM +0100, abdellatif.elkhlifi@arm.com wrote:
> > > > > > > > > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > > > > > >
> > > > > > > > > This patchset adds support for Arm FF-A (Arm Firmware Framework for Armv8-A v1.0).
> > > > > > > > >
> > > > > > > > > FF-A support is generic by design and can be used by any Arm platform.
> > > > > > > > >
> > > > > > > > > The features added are as follows:
> > > > > > > > >
> > > > > > > > > 1/ FF-A device driver
> > > > > > > > > 2/ armffa command
> > > > > > > > > 3/ FF-A Sandbox driver
> > > > > > > > > 4/ FF-A Sandbox test cases
> > > > > > > > > 5/ FF-A MM communication
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > The suggested design sees FF-A as a data bus allowing data exchange with the firmware
> > > > > > > > > running under TrustZone HW (such as Optee). The same approach was followed in the
> > > > > > > > > FF-A driver in Linux kernel (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211))
> > > > > > > > >
> > > > > > > > > u-boot boards using FF-A can provide a device tree node in a <board>-u-boot.dtsi file.
> > > > > > > > > Since the node can not be hosted in Linux device tree, we suggest using u-boot device tree.
> > > > > > > >
> > > > > > > > Why can't the node be in the upstream tree?  It should be, so that it
> > > > > > > > can be shared between all users.  Especially since there's in-Linux
> > > > > > > > users?
> > > > > > > >
> > > > > > > > --
> > > > > > > > Tom
> > > > > > >
> > > > > > > Linux already has an FF-A bus driver and doesn't use a device tree node for FF-A.
> > > > > > >
> > > > > > > The Linux driver registers FF-A as a bus:
> > > > > > >
> > > > > > > int arm_ffa_bus_init(void)
> > > > > > > {
> > > > > > >   return bus_register(&ffa_bus_type);
> > > > > > > }
> > > > > > >
> > > > > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/arm_ffa/bus.c?h=v5.15#n211
> > > > > > >
> > > > > > > So, there is no user for the node in Linux. That's why we suggest hosting the node in the u-boot device tree (a u-boot.dtsi file)
> > > > > >
> > > > > > OK, but you can still push it upstream as it's not required to have an
> > > > > > in tree user.
> > > > >
> > > > > During the review of Corstone-1000 patchset, Rui Silva had a discussion with the Linux device tree maintainer
> > > > > (Rob Herring). Rob is not in favour of an FFA node in the kernel device tree. This is why we are including the FFA node
> > > > > in u-boot device tree (u-boot.dtsi files).
> > >
> > > Sigh. There is not a 'kernel device tree' and a 'u-boot device tree'.
> > > There is only 1. For SystemReadyIR compliance, that is a hard
> > > requirement.
> > >
> > > > I'm a bit confused now, can you please link to the kernel thread?  Or
> > > > Rob, can you chime in here please?
> > >
> > > The FFA DT binding was rejected in favor of making FFA discoverable.
> > > The FFA spec was amended to address that. DT is only for what we
> > > failed to make discoverable. For hardware, we're stuck with it. We
> > > shouldn't repeat that for software interfaces.
> > >
> > > Rob
> >
> > Guys,
> >
> > Since we can not add an FFA node in the device tree, we will make FFA a discoverable bus.
> > So, we will manually create the udevice, binding it to the driver and probing it.
> > Manually means directly calling device_bind and device_probe APIs.
> >
> > Any thoughts about this approach ?
>
> How is it both discoverable and doesn't have a device tree node, in the
> kernel?

Also, if it is discoverable, we can still use U-Boot to discover it
and then pass the info to Linux in the DT.

I am seeing several series which don't have 'proper' DT bindings in
Linux. First I heard it was for legacy reasons, but now I am hearing
something different. For U-Boot, we really do need to have DT bindings
for devices. All this ad-hoc creation of stuff makes things hard to
discover, adds to code size and makes things like of-platdata
impossible.

Furthermore, if the bindings affect U-Boot, then the U-Boot project
should have a say in what is being done there, not just be downstream
of all such changes.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-08-01 19:13                 ` [PATCH 0/6] introduce Arm FF-A support Simon Glass
@ 2022-08-01 19:28                   ` Sudeep Holla
  2022-08-02  3:08                     ` Simon Glass
  2022-08-02 12:22                     ` Tom Rini
  0 siblings, 2 replies; 478+ messages in thread
From: Sudeep Holla @ 2022-08-01 19:28 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Abdellatif El Khlifi, Rob Herring, Sudeep Holla,
	. Ilias Apalodimas, achin.gupta, Rui Miguel Silva,
	vishnu.banavath, xueliang.zhong, U-Boot Mailing List

On Mon, Aug 01, 2022 at 01:13:23PM -0600, Simon Glass wrote:
> On Wed, 13 Apr 2022 at 10:46, Tom Rini <trini@konsulko.com> wrote:
> >
> > How is it both discoverable and doesn't have a device tree node, in the
> > kernel?
>
> Also, if it is discoverable, we can still use U-Boot to discover it
> and then pass the info to Linux in the DT.
>

Why ? Linux can discover the presence of the feature with a simple SMCCC
based query. We don't need any DT bindings for this particular feature.
Not sure if you are talking in general or in the context of $subject
feature in the kernel.

> I am seeing several series which don't have 'proper' DT bindings in
> Linux. First I heard it was for legacy reasons, but now I am hearing
> something different. For U-Boot, we really do need to have DT bindings
> for devices. All this ad-hoc creation of stuff makes things hard to
> discover, adds to code size and makes things like of-platdata
> impossible.
>

I may not have the complete picture here. If you are saying that every
feature in the u-boot needs DT for some reason, then that's U-boot's
limitation or restriction. But just the presence of node means nothing
until the corresponding feature is queried and confirmed to be present
in the firmware. That is very important as we can't skip the query stage
just because of presence of some DT node for this.

> Furthermore, if the bindings affect U-Boot, then the U-Boot project
> should have a say in what is being done there, not just be downstream
> of all such changes.
>

I still think you talking about some issue in general and it doesn't
apply in this case. The new firmware interfaces are designed to be
discoverable which is the main advantage over any non discoverable
hardware and/or firmware interface. One main advantage I see is that we
don't need any DT bindings which makes the firmware upgrades must simpler
as the users can query the interface and know exactly what they need
instead of relying on DT node which may get stale if not updated with the
firmware update. I am not sure if whatever I am writing here is relevant
to what your concerns are as I think I haven't understood them fully.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-08-01 19:28                   ` Sudeep Holla
@ 2022-08-02  3:08                     ` Simon Glass
  2022-08-02  8:38                       ` Sudeep Holla
  2022-08-05 11:15                       ` Abdellatif El Khlifi
  2022-08-02 12:22                     ` Tom Rini
  1 sibling, 2 replies; 478+ messages in thread
From: Simon Glass @ 2022-08-02  3:08 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Tom Rini, Abdellatif El Khlifi, Rob Herring, . Ilias Apalodimas,
	achin.gupta, Rui Miguel Silva, vishnu.banavath, xueliang.zhong,
	U-Boot Mailing List

Hi Sudeep,

On Mon, 1 Aug 2022 at 13:28, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Mon, Aug 01, 2022 at 01:13:23PM -0600, Simon Glass wrote:
> > On Wed, 13 Apr 2022 at 10:46, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > How is it both discoverable and doesn't have a device tree node, in the
> > > kernel?
> >
> > Also, if it is discoverable, we can still use U-Boot to discover it
> > and then pass the info to Linux in the DT.
> >
>
> Why ? Linux can discover the presence of the feature with a simple SMCCC
> based query. We don't need any DT bindings for this particular feature.
> Not sure if you are talking in general or in the context of $subject
> feature in the kernel.

Oh well my understanding of Open Firmware was that the firmware did
the probing and passed the info to the OS.

>
> > I am seeing several series which don't have 'proper' DT bindings in
> > Linux. First I heard it was for legacy reasons, but now I am hearing
> > something different. For U-Boot, we really do need to have DT bindings
> > for devices. All this ad-hoc creation of stuff makes things hard to
> > discover, adds to code size and makes things like of-platdata
> > impossible.
> >
>
> I may not have the complete picture here. If you are saying that every
> feature in the u-boot needs DT for some reason, then that's U-boot's
> limitation or restriction. But just the presence of node means nothing

Yes it is something I am becoming more and more concerned about.

> until the corresponding feature is queried and confirmed to be present
> in the firmware. That is very important as we can't skip the query stage
> just because of presence of some DT node for this.
>
> > Furthermore, if the bindings affect U-Boot, then the U-Boot project
> > should have a say in what is being done there, not just be downstream
> > of all such changes.
> >
>
> I still think you talking about some issue in general and it doesn't
> apply in this case. The new firmware interfaces are designed to be
> discoverable which is the main advantage over any non discoverable
> hardware and/or firmware interface. One main advantage I see is that we
> don't need any DT bindings which makes the firmware upgrades must simpler
> as the users can query the interface and know exactly what they need
> instead of relying on DT node which may get stale if not updated with the
> firmware update. I am not sure if whatever I am writing here is relevant
> to what your concerns are as I think I haven't understood them fully.

I'm not sure either. In particular I'm not sure why it would be easier
to update whatever the FF-A software is than to update the DT, since
presumably they are both in the firmware.

I am talking about an issue in general and the same issue in
particular with this series.

Can I suggest resending this series with a change log for each patch.
Also please try to avoid #ifdefs and make sure to include
documentation in doc/ including how this relates to the UEFI
firmware-update effort that ARM/Linaro is undertaking. Also, what
happened to the tests / sandbox driver?

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-08-02  3:08                     ` Simon Glass
@ 2022-08-02  8:38                       ` Sudeep Holla
  2022-08-05 11:15                       ` Abdellatif El Khlifi
  1 sibling, 0 replies; 478+ messages in thread
From: Sudeep Holla @ 2022-08-02  8:38 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Abdellatif El Khlifi, Rob Herring, Ilias Apalodimas,
	achin.gupta, Rui Miguel Silva, vishnu.banavath, xueliang.zhong,
	U-Boot Mailing List

Hi Simon,

On Mon, Aug 01, 2022 at 09:08:00PM -0600, Simon Glass wrote:
> Hi Sudeep,
>
> I'm not sure either. In particular I'm not sure why it would be easier
> to update whatever the FF-A software is than to update the DT, since
> presumably they are both in the firmware.
>

No, that is not the point. Someone who integrates must be aware of the
fact that since the firmware is updated, there is a dependency(though
created unnecessarily in this case) to even update the DT. Missing that
may result in spending time and finding it hard way. It may not happen
often but still happens and worth saving time and effort if this unneeded
dependency is wasn't there.

> I am talking about an issue in general and the same issue in
> particular with this series.
>

Since I might be missing to fully understand the issue, I may not be
of much help I am afraid.

> Can I suggest resending this series with a change log for each patch.
> Also please try to avoid #ifdefs and make sure to include
> documentation in doc/ including how this relates to the UEFI
> firmware-update effort that ARM/Linaro is undertaking. Also, what
> happened to the tests / sandbox driver?

To give a extremely brief summary on FF-A, it is an interface that enables
standard way of communication between different partitions in the system.
Partitions(also referred as VMs sometimes) can be either secure or
non-secure. Though it can be use to communicate between 2 non-secure VMs,
it is unlikely to be use there as it is not arch agnostic. So it will be
mainly used between secure and non-secure partitions and amongst secure
partitions.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-08-01 19:28                   ` Sudeep Holla
  2022-08-02  3:08                     ` Simon Glass
@ 2022-08-02 12:22                     ` Tom Rini
  2022-08-02 13:45                       ` Sudeep Holla
  2022-08-03 10:14                       ` Abdellatif El Khlifi
  1 sibling, 2 replies; 478+ messages in thread
From: Tom Rini @ 2022-08-02 12:22 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Simon Glass, Abdellatif El Khlifi, Rob Herring,
	. Ilias Apalodimas, achin.gupta, Rui Miguel Silva,
	vishnu.banavath, xueliang.zhong, U-Boot Mailing List

[-- Attachment #1: Type: text/plain, Size: 2967 bytes --]

On Mon, Aug 01, 2022 at 08:28:08PM +0100, Sudeep Holla wrote:
> On Mon, Aug 01, 2022 at 01:13:23PM -0600, Simon Glass wrote:
> > On Wed, 13 Apr 2022 at 10:46, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > How is it both discoverable and doesn't have a device tree node, in the
> > > kernel?
> >
> > Also, if it is discoverable, we can still use U-Boot to discover it
> > and then pass the info to Linux in the DT.
> >
> 
> Why ? Linux can discover the presence of the feature with a simple SMCCC
> based query. We don't need any DT bindings for this particular feature.
> Not sure if you are talking in general or in the context of $subject
> feature in the kernel.
> 
> > I am seeing several series which don't have 'proper' DT bindings in
> > Linux. First I heard it was for legacy reasons, but now I am hearing
> > something different. For U-Boot, we really do need to have DT bindings
> > for devices. All this ad-hoc creation of stuff makes things hard to
> > discover, adds to code size and makes things like of-platdata
> > impossible.
> >
> 
> I may not have the complete picture here. If you are saying that every
> feature in the u-boot needs DT for some reason, then that's U-boot's
> limitation or restriction. But just the presence of node means nothing
> until the corresponding feature is queried and confirmed to be present
> in the firmware. That is very important as we can't skip the query stage
> just because of presence of some DT node for this.
> 
> > Furthermore, if the bindings affect U-Boot, then the U-Boot project
> > should have a say in what is being done there, not just be downstream
> > of all such changes.
> >
> 
> I still think you talking about some issue in general and it doesn't
> apply in this case. The new firmware interfaces are designed to be
> discoverable which is the main advantage over any non discoverable
> hardware and/or firmware interface. One main advantage I see is that we
> don't need any DT bindings which makes the firmware upgrades must simpler
> as the users can query the interface and know exactly what they need
> instead of relying on DT node which may get stale if not updated with the
> firmware update. I am not sure if whatever I am writing here is relevant
> to what your concerns are as I think I haven't understood them fully.

Part of the problem I think here is who does have a more complete
picture of things? Saying there's a DT binding available is generally
the firmware interface for discovering something exists somewhere else
(excepting buses that define a discovery protocol).  Except not in this
case where there's a different interface. So who defined that interface
and where is it specified? What's already been accepted upstream to
other projects?

We're on I think v4 of this series now, and it was this email here that
explained that an SMCCC call is how Linux finds out this exists (or
doesn't exist).

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-08-02 12:22                     ` Tom Rini
@ 2022-08-02 13:45                       ` Sudeep Holla
  2022-08-03 10:14                       ` Abdellatif El Khlifi
  1 sibling, 0 replies; 478+ messages in thread
From: Sudeep Holla @ 2022-08-02 13:45 UTC (permalink / raw)
  To: Tom Rini
  Cc: Simon Glass, Abdellatif El Khlifi, Rob Herring, Sudeep Holla,
	. Ilias Apalodimas, achin.gupta, Rui Miguel Silva,
	vishnu.banavath, xueliang.zhong, U-Boot Mailing List

On Tue, Aug 02, 2022 at 08:22:19AM -0400, Tom Rini wrote:
> On Mon, Aug 01, 2022 at 08:28:08PM +0100, Sudeep Holla wrote:
> > On Mon, Aug 01, 2022 at 01:13:23PM -0600, Simon Glass wrote:
> > > On Wed, 13 Apr 2022 at 10:46, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > How is it both discoverable and doesn't have a device tree node, in the
> > > > kernel?
> > >
> > > Also, if it is discoverable, we can still use U-Boot to discover it
> > > and then pass the info to Linux in the DT.
> > >
> > 
> > Why ? Linux can discover the presence of the feature with a simple SMCCC
> > based query. We don't need any DT bindings for this particular feature.
> > Not sure if you are talking in general or in the context of $subject
> > feature in the kernel.
> > 
> > > I am seeing several series which don't have 'proper' DT bindings in
> > > Linux. First I heard it was for legacy reasons, but now I am hearing
> > > something different. For U-Boot, we really do need to have DT bindings
> > > for devices. All this ad-hoc creation of stuff makes things hard to
> > > discover, adds to code size and makes things like of-platdata
> > > impossible.
> > >
> > 
> > I may not have the complete picture here. If you are saying that every
> > feature in the u-boot needs DT for some reason, then that's U-boot's
> > limitation or restriction. But just the presence of node means nothing
> > until the corresponding feature is queried and confirmed to be present
> > in the firmware. That is very important as we can't skip the query stage
> > just because of presence of some DT node for this.
> > 
> > > Furthermore, if the bindings affect U-Boot, then the U-Boot project
> > > should have a say in what is being done there, not just be downstream
> > > of all such changes.
> > >
> > 
> > I still think you talking about some issue in general and it doesn't
> > apply in this case. The new firmware interfaces are designed to be
> > discoverable which is the main advantage over any non discoverable
> > hardware and/or firmware interface. One main advantage I see is that we
> > don't need any DT bindings which makes the firmware upgrades must simpler
> > as the users can query the interface and know exactly what they need
> > instead of relying on DT node which may get stale if not updated with the
> > firmware update. I am not sure if whatever I am writing here is relevant
> > to what your concerns are as I think I haven't understood them fully.
> 
> Part of the problem I think here is who does have a more complete
> picture of things? Saying there's a DT binding available is generally
> the firmware interface for discovering something exists somewhere else
> (excepting buses that define a discovery protocol).  Except not in this
> case where there's a different interface. So who defined that interface
> and where is it specified? What's already been accepted upstream to
> other projects?
>

Understood and agreed. Definitely need more background to sell some new
feature.

> We're on I think v4 of this series now, and it was this email here that
> explained that an SMCCC call is how Linux finds out this exists (or
> doesn't exist).
>

Ah that explains some of the confusion. Sorry I was not fully involved
in u-boot support in general and didn't pay much attention to the previous
versions. I would have presented the pointer to the specification to
start with instead of just the reference to the kernel implementation
as that might be biasing as well as the requirements may differ between
u-boot and the kernel.

Anyways, here is the specification[1]. Also in general, there are quite a
few new firmware interface based on SMCCC in the recent years and most of
them take care to ensure they can be discovered.

-- 
Regards,
Sudeep

[1] https://developer.arm.com/documentation/den0077/latest

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-08-02 12:22                     ` Tom Rini
  2022-08-02 13:45                       ` Sudeep Holla
@ 2022-08-03 10:14                       ` Abdellatif El Khlifi
  1 sibling, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-08-03 10:14 UTC (permalink / raw)
  To: Tom Rini
  Cc: Sudeep Holla, Simon Glass, Rob Herring, . Ilias Apalodimas,
	achin.gupta, vishnu.banavath, xueliang.zhong,
	U-Boot Mailing List, nd

On Tue, Aug 02, 2022 at 08:22:19AM -0400, Tom Rini wrote:
> On Mon, Aug 01, 2022 at 08:28:08PM +0100, Sudeep Holla wrote:
> > On Mon, Aug 01, 2022 at 01:13:23PM -0600, Simon Glass wrote:
> > > On Wed, 13 Apr 2022 at 10:46, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > How is it both discoverable and doesn't have a device tree node, in the
> > > > kernel?
> > >
> > > Also, if it is discoverable, we can still use U-Boot to discover it
> > > and then pass the info to Linux in the DT.
> > >
> > 
> > Why ? Linux can discover the presence of the feature with a simple SMCCC
> > based query. We don't need any DT bindings for this particular feature.
> > Not sure if you are talking in general or in the context of $subject
> > feature in the kernel.
> > 
> > > I am seeing several series which don't have 'proper' DT bindings in
> > > Linux. First I heard it was for legacy reasons, but now I am hearing
> > > something different. For U-Boot, we really do need to have DT bindings
> > > for devices. All this ad-hoc creation of stuff makes things hard to
> > > discover, adds to code size and makes things like of-platdata
> > > impossible.
> > >
> > 
> > I may not have the complete picture here. If you are saying that every
> > feature in the u-boot needs DT for some reason, then that's U-boot's
> > limitation or restriction. But just the presence of node means nothing
> > until the corresponding feature is queried and confirmed to be present
> > in the firmware. That is very important as we can't skip the query stage
> > just because of presence of some DT node for this.
> > 
> > > Furthermore, if the bindings affect U-Boot, then the U-Boot project
> > > should have a say in what is being done there, not just be downstream
> > > of all such changes.
> > >
> > 
> > I still think you talking about some issue in general and it doesn't
> > apply in this case. The new firmware interfaces are designed to be
> > discoverable which is the main advantage over any non discoverable
> > hardware and/or firmware interface. One main advantage I see is that we
> > don't need any DT bindings which makes the firmware upgrades must simpler
> > as the users can query the interface and know exactly what they need
> > instead of relying on DT node which may get stale if not updated with the
> > firmware update. I am not sure if whatever I am writing here is relevant
> > to what your concerns are as I think I haven't understood them fully.
> 
> Part of the problem I think here is who does have a more complete
> picture of things? Saying there's a DT binding available is generally
> the firmware interface for discovering something exists somewhere else
> (excepting buses that define a discovery protocol).  Except not in this
> case where there's a different interface. So who defined that interface
> and where is it specified? What's already been accepted upstream to
> other projects?
> 
> We're on I think v4 of this series now, and it was this email here that
> explained that an SMCCC call is how Linux finds out this exists (or
> doesn't exist).
> 
> -- 
> Tom

Hi guys,

All your feedbacks are valuable and more than welcome. Thanks for all of you.

Sorry for any confusion, I'd like to highlight the following points:

1/ FF-A spec:

cover letter v1 already states that this work provides support for Arm Firmware Framework for Armv8-A v1.0 (please see [A])

Also, in the v1 patchset the documentation of the main config enabling the driver states that we are using the FF-A spec and the link is provided:

in ARM_FFA_TRANSPORT config:
+	  This driver is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en

Please refer to [B] for more details.

2/ Linux:

The linux kernel driver has been referred to for showing that in linux FF-A is considered as a data bus and not just as a FW interface.

3/ FF-A bus discovery in u-boot:

In patchset v1 the FF-A bus was probed through a device tree node. Then, we got feedbacks from the device tree maintainer stating this won't be accepted.

This is why v2 version comes into the picture by making FF-A bus discoverable using device_{bind, probe} API

FF-A bus discovery in u-boot succeeds when all these operations are successful:

- querying the FF-A framework version
- querying from secure world the u-boot endpoint ID
- querying from secure world the supported features of the specified FF-A calls
- mapping the RX/TX buffers
- querying from secure world all the partitions information

These are done at ffa_probe level.

+/**
+ * ffa_probe - The driver probe function
+ * @dev:	the arm_ffa device
+ *
+ * Probing is done at boot time and triggered by the uclass device discovery.
+ * At probe level the following actions are done:
+ *	- setting the conduit
+ *	- querying the FF-A framework version
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of the specified FF-A calls
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information


In patchset v2 , ffa_bus_discover has been introduced and documented in the header (please refer to [D] and check the documentation of the functions: ffa_bus_discover , ffa_probe, ffa_get_device)

+	/* The FF-A bus discovery succeeds when probing is successful */
+	ret = device_probe(ffa_priv_data.dev);

4/ Feedbacks from Linaro:

We got new feedbacks from Linaro and we agreed to align the driver interfaces with those used in the kernel driver. Furthermore, we got a new requirement to make the driver independent from EFI. v3 patchset addresses that.

5/ in v3 cover letter, the full history of what each version brings are listed (please see [C])

6/ A detailed readme document has recently been written and will be added in the upcoming v4 patchset

cover letter 1:
[A] https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/

kconfig of the driver:
[B] https://lore.kernel.org/all/20220329151659.16894-2-abdellatif.elkhlifi@arm.com/#Z31drivers:arm-ffa:Kconfig

cover letter 3:
[C] https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/

patch introducing FF-A discovery:
[D] https://lore.kernel.org/all/20220415122803.16666-2-abdellatif.elkhlifi@arm.com/


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-08-02  3:08                     ` Simon Glass
  2022-08-02  8:38                       ` Sudeep Holla
@ 2022-08-05 11:15                       ` Abdellatif El Khlifi
  2022-08-05 16:48                         ` Simon Glass
  1 sibling, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-08-05 11:15 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, nd

On Mon, Aug 01, 2022 at 09:08:00PM -0600, Simon Glass wrote:
> Hi Sudeep,
> 
> On Mon, 1 Aug 2022 at 13:28, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Mon, Aug 01, 2022 at 01:13:23PM -0600, Simon Glass wrote:
> > > On Wed, 13 Apr 2022 at 10:46, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > How is it both discoverable and doesn't have a device tree node, in the
> > > > kernel?
> > >
> > > Also, if it is discoverable, we can still use U-Boot to discover it
> > > and then pass the info to Linux in the DT.
> > >
> >
> > Why ? Linux can discover the presence of the feature with a simple SMCCC
> > based query. We don't need any DT bindings for this particular feature.
> > Not sure if you are talking in general or in the context of $subject
> > feature in the kernel.
> 
> Oh well my understanding of Open Firmware was that the firmware did
> the probing and passed the info to the OS.
> 
> >
> > > I am seeing several series which don't have 'proper' DT bindings in
> > > Linux. First I heard it was for legacy reasons, but now I am hearing
> > > something different. For U-Boot, we really do need to have DT bindings
> > > for devices. All this ad-hoc creation of stuff makes things hard to
> > > discover, adds to code size and makes things like of-platdata
> > > impossible.
> > >
> >
> > I may not have the complete picture here. If you are saying that every
> > feature in the u-boot needs DT for some reason, then that's U-boot's
> > limitation or restriction. But just the presence of node means nothing
> 
> Yes it is something I am becoming more and more concerned about.
> 
> > until the corresponding feature is queried and confirmed to be present
> > in the firmware. That is very important as we can't skip the query stage
> > just because of presence of some DT node for this.
> >
> > > Furthermore, if the bindings affect U-Boot, then the U-Boot project
> > > should have a say in what is being done there, not just be downstream
> > > of all such changes.
> > >
> >
> > I still think you talking about some issue in general and it doesn't
> > apply in this case. The new firmware interfaces are designed to be
> > discoverable which is the main advantage over any non discoverable
> > hardware and/or firmware interface. One main advantage I see is that we
> > don't need any DT bindings which makes the firmware upgrades must simpler
> > as the users can query the interface and know exactly what they need
> > instead of relying on DT node which may get stale if not updated with the
> > firmware update. I am not sure if whatever I am writing here is relevant
> > to what your concerns are as I think I haven't understood them fully.
> 
> I'm not sure either. In particular I'm not sure why it would be easier
> to update whatever the FF-A software is than to update the DT, since
> presumably they are both in the firmware.
> 
> I am talking about an issue in general and the same issue in
> particular with this series.
> 
> Can I suggest resending this series with a change log for each patch.
> Also please try to avoid #ifdefs and make sure to include
> documentation in doc/ including how this relates to the UEFI
> firmware-update effort that ARM/Linaro is undertaking. Also, what
> happened to the tests / sandbox driver?
> 
> Regards,
> Simon

Hi Simon,

OK, the next patchset update gonna include:

- A change log for each patch
- Less #ifdefs
- A detailed readme under doc/

The full history of what each patchset version brings are listed in v3 cover letter: please see [1]. It also contains a note about sandbox, saying that updating sandbox driver and tests is work in progress.

A note regarding the use of #ifdefs:

In some cases we need to use them. For example:

- Including the driver header which exports APIs and data structures only relevant when FF-A is enabled. This needs to be decided at build time. Some platforms don't want to build FF-A code at all.
- At initcall level like done for other busses. an #ifdef is used to add an initcall for bus discovery. When FF-A is not needed, the discovery function will not be build at all (saves memory).

[1] https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/

Cheers,
Abdellatif


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v3 1/4] arm64: smccc: add Xn registers support used by SMC calls
  2022-08-01 18:41                                 ` Sudeep Holla
@ 2022-08-05 11:17                                   ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-08-05 11:17 UTC (permalink / raw)
  To: Sudeep Holla; +Cc: u-boot, nd

On Mon, Aug 01, 2022 at 07:41:16PM +0100, Sudeep Holla wrote:
> On Mon, Aug 01, 2022 at 06:20:50PM +0100, Abdellatif El Khlifi wrote:
> > use x0-x17 registers in the SMC32/SMC64 calls according to SMCCCv1.2
> > 
> > Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> 
> Please drop my signed-off as I didn't. I am seeing this patch on the list
> for the first time and AFAIK I haven't posted any previous version of the
> patch that you are picking up.
> 
> IIUC, you are importing this code from the Linux kernel tree which I assume
> is fine. You can just mention the same and must not add anyone's sign-off
> without consulting them.
> 
> OTH, if you cherry-pick the commit as is and use it in u-boot tree(e.g.
> DTS patches), then you can retain them. That is my understanding. Happy
> to be corrected if my assumptions are not correct here.
> 
> --
> Regards,
> Sudeep

No worries. I'll remove the signed-off. I just wanted to give credit to the original author :)

For the FF-A driver in u-boot, only the SMC part of the kernel patch is needed. No need for HVC
support at the moment. The SMC part has been tested and proven to work. Hence, this patch.

I'll rename this commit to:

arm64: smccc: add support for SMCCCv1.2 x0-x17 registers

I'll also state in the commit description that this work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

You're welcome to provide review comments.

Cheers,
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 0/6] introduce Arm FF-A support
  2022-08-05 11:15                       ` Abdellatif El Khlifi
@ 2022-08-05 16:48                         ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2022-08-05 16:48 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: U-Boot Mailing List, nd

Hi Abdellatif,

On Fri, 5 Aug 2022 at 05:15, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> On Mon, Aug 01, 2022 at 09:08:00PM -0600, Simon Glass wrote:
> > Hi Sudeep,
> >
> > On Mon, 1 Aug 2022 at 13:28, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > >
> > > On Mon, Aug 01, 2022 at 01:13:23PM -0600, Simon Glass wrote:
> > > > On Wed, 13 Apr 2022 at 10:46, Tom Rini <trini@konsulko.com> wrote:
> > > > >
> > > > > How is it both discoverable and doesn't have a device tree node, in the
> > > > > kernel?
> > > >
> > > > Also, if it is discoverable, we can still use U-Boot to discover it
> > > > and then pass the info to Linux in the DT.
> > > >
> > >
> > > Why ? Linux can discover the presence of the feature with a simple SMCCC
> > > based query. We don't need any DT bindings for this particular feature.
> > > Not sure if you are talking in general or in the context of $subject
> > > feature in the kernel.
> >
> > Oh well my understanding of Open Firmware was that the firmware did
> > the probing and passed the info to the OS.
> >
> > >
> > > > I am seeing several series which don't have 'proper' DT bindings in
> > > > Linux. First I heard it was for legacy reasons, but now I am hearing
> > > > something different. For U-Boot, we really do need to have DT bindings
> > > > for devices. All this ad-hoc creation of stuff makes things hard to
> > > > discover, adds to code size and makes things like of-platdata
> > > > impossible.
> > > >
> > >
> > > I may not have the complete picture here. If you are saying that every
> > > feature in the u-boot needs DT for some reason, then that's U-boot's
> > > limitation or restriction. But just the presence of node means nothing
> >
> > Yes it is something I am becoming more and more concerned about.
> >
> > > until the corresponding feature is queried and confirmed to be present
> > > in the firmware. That is very important as we can't skip the query stage
> > > just because of presence of some DT node for this.
> > >
> > > > Furthermore, if the bindings affect U-Boot, then the U-Boot project
> > > > should have a say in what is being done there, not just be downstream
> > > > of all such changes.
> > > >
> > >
> > > I still think you talking about some issue in general and it doesn't
> > > apply in this case. The new firmware interfaces are designed to be
> > > discoverable which is the main advantage over any non discoverable
> > > hardware and/or firmware interface. One main advantage I see is that we
> > > don't need any DT bindings which makes the firmware upgrades must simpler
> > > as the users can query the interface and know exactly what they need
> > > instead of relying on DT node which may get stale if not updated with the
> > > firmware update. I am not sure if whatever I am writing here is relevant
> > > to what your concerns are as I think I haven't understood them fully.
> >
> > I'm not sure either. In particular I'm not sure why it would be easier
> > to update whatever the FF-A software is than to update the DT, since
> > presumably they are both in the firmware.
> >
> > I am talking about an issue in general and the same issue in
> > particular with this series.
> >
> > Can I suggest resending this series with a change log for each patch.
> > Also please try to avoid #ifdefs and make sure to include
> > documentation in doc/ including how this relates to the UEFI
> > firmware-update effort that ARM/Linaro is undertaking. Also, what
> > happened to the tests / sandbox driver?
> >
> > Regards,
> > Simon
>
> Hi Simon,
>
> OK, the next patchset update gonna include:
>
> - A change log for each patch
> - Less #ifdefs
> - A detailed readme under doc/
>
> The full history of what each patchset version brings are listed in v3 cover letter: please see [1]. It also contains a note about sandbox, saying that updating sandbox driver and tests is work in progress.

Thanks for the email. OK, let's get that work completed before this goes in.

Also, if you use patman (for both U-Boot and Linux) it does the change
logs for you and combines them all into the cover letter too, among
other things.

>
> A note regarding the use of #ifdefs:
>
> In some cases we need to use them. For example:
>
> - Including the driver header which exports APIs and data structures only relevant when FF-A is enabled. This needs to be decided at build time. Some platforms don't want to build FF-A code at all.

I think it is fine in header files when needed, as you say. We should
try to avoid them in C files.

> - At initcall level like done for other busses. an #ifdef is used to add an initcall for bus discovery. When FF-A is not needed, the discovery function will not be build at all (saves memory).

We'll need to discuss this as driver model handles devices in U-Boot.
Will wait to see what you come up with.

>
> [1] https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver
  2022-08-01 17:20                               ` [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
@ 2022-08-12  7:39                                 ` Ilias Apalodimas
  2022-09-26 11:11                                   ` Abdellatif El Khlifi
  2022-08-13  2:21                                 ` Simon Glass
  2022-11-15 15:24                                 ` Simon Glass
  2 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2022-08-12  7:39 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: jens.wiklander, achin.gupta, trini, u-boot, vishnu.banavath,
	xueliang.zhong, nd

Hi Abdellatif,

On Mon, 1 Aug 2022 at 20:21, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
>
> The Firmware Framework for Arm A-profile processors (FF-A)
> describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World leveraging TrustZone
> technology.
>
> This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> querying the FF-A framework from the secure world.
>
> 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
>
> In u-boot FF-A design, FF-A is considered as a discoverable bus.
> The Secure World is considered as one entity to communicate with
> using the FF-A bus. FF-A communication is handled by one device and
> one instance (the bus). This FF-A driver takes care of all the
> interactions between Normal world and Secure World.
>
> The driver exports its operations to be used by upper layers.
>
> Exported operations:
>
> - partition_info_get
> - sync_send_receive
> - rxtx_unmap
>
> This implementation provides an optional feature to copy the driver data
> to EFI runtime area.
>

[...]

> +config ARM_FFA_TRANSPORT
> +       bool "Enable Arm Firmware Framework for Armv8-A driver"
> +       depends on DM && ARM64
> +       select ARM_SMCCC
> +       select LIB_UUID
> +       select DEVRES
> +       help
> +         The Firmware Framework for Arm A-profile processors (FF-A)
> +         describes interfaces (ABIs) that standardize communication
> +         between the Secure World and Normal World leveraging TrustZone
> +         technology.
> +
> +         This driver is based on FF-A specification v1.0 and uses SMC32
> +         calling convention.
> +
> +         FF-A specification:
> +
> +         https://developer.arm.com/documentation/den0077/a/?lang=en
> +
> +         In u-boot FF-A design, FF-A is considered as a discoverable bus.
> +         The Secure World is considered as one entity to communicate with
> +         using the FF-A bus.
> +         FF-A communication is handled by one device and one instance (the bus).
> +         This FF-A driver takes care of all the interactions between Normal world
> +         and Secure World.
> +
> +config ARM_FFA_EFI_RUNTIME_MODE
> +       bool "Enable EFI runtime support for FF-A data and code "
> +       depends on ARM_FFA_TRANSPORT && EFI_LOADER
> +       help
> +         Allows FF-A driver data structures and code to be accessible at EFI runtime

Is there a reason we want to opt-in on that?  What prevents it from
always being  there?

[...]

> +
> +/* Endpoint ID mask (u-boot endpoint ID) */
> +
> +#define GET_SELF_ENDPOINT_ID_MASK              GENMASK(15, 0)
> +#define GET_SELF_ENDPOINT_ID(x)                \
> +                       ((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> +
> +#define PREP_SELF_ENDPOINT_ID_MASK             GENMASK(31, 16)
> +#define PREP_SELF_ENDPOINT_ID(x)               \
> +                       (FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> +
> +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> +
> +#define PREP_PART_ENDPOINT_ID_MASK             GENMASK(15, 0)
> +#define PREP_PART_ENDPOINT_ID(x)               \
> +                       (FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> +
> +/*
> + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> + */
> +
> +#define FFA_SMC(calling_convention, func_num)                          \
> +       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),   \
> +                          ARM_SMCCC_OWNER_STANDARD, (func_num))
> +
> +#define FFA_SMC_32(func_num)                           FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> +#define FFA_SMC_64(func_num)                           FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
> +
> +#define FFA_VERSION                            FFA_SMC_32(0x63)
> +#define FFA_ID_GET                             FFA_SMC_32(0x69)
> +#define FFA_FEATURES                           FFA_SMC_32(0x64)
> +#define FFA_PARTITION_INFO_GET                 FFA_SMC_32(0x68)
> +#define FFA_RXTX_UNMAP                         FFA_SMC_32(0x67)
> +#define FFA_RX_RELEASE                         FFA_SMC_32(0x65)
> +#define FFA_RUN                                        FFA_SMC_32(0x6D)
> +#define FFA_ERROR                              FFA_SMC_32(0x60)
> +#define FFA_SUCCESS                            FFA_SMC_32(0x61)
> +#define FFA_INTERRUPT                          FFA_SMC_32(0x62)
> +#define FFA_RXTX_MAP                           FFA_SMC_64(0x66)
> +#define FFA_MSG_SEND_DIRECT_REQ                        FFA_SMC_64(0x6F)
> +#define FFA_MSG_SEND_DIRECT_RESP               FFA_SMC_64(0x70)
> +
> +/* 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);
> +
> +/* FF-A error codes */
> +#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_INTERRUPTED                               (-5)
> +#define FFA_ERR_STAT_DENIED                            (-6)
> +#define FFA_ERR_STAT_RETRY                             (-7)
> +#define FFA_ERR_STAT_ABORTED                           (-8)
> +
> +/* UUID data size */
> +#define UUID_SIZE (16)

Please drop () on these

> +
> +/*
> + * union ffa_partition_uuid - Data union hosting the UUID
> + *                                                     transmitted by FFA_PARTITION_INFO_GET
> + * @words:     data structure giving 32-bit words access to the UUID data
> + * @bytes:     data structure giving byte access to the UUID data
> + *
> + * The structure holds little-endian UUID data.
> + */
> +union ffa_partition_uuid {
> +       struct __packed words {
> +       u32 a1; /* w1 */
> +       u32 a2; /* w2 */
> +       u32 a3; /* w3 */
> +       u32 a4; /* w4 */
> +       } words;
> +       u8 bytes[UUID_SIZE];
> +};

is the bytes field used anywhere?

[...]

> + *
> + * Each partition has its descriptor containing the partitions information and the UUID
> + */
> +struct ffa_partition_desc {
> +       struct ffa_partition_info info;
> +       union ffa_partition_uuid UUID;

lower case please and perhaps a better name e.g partition_uuid

> +};
> +
> +/**
> + * struct ffa_partitions - descriptors for all secure partitions
> + * @count:     The number of partitions descriptors
> + * @descs      The partitions descriptors table
> + *
> + * This data structure contains the partitions descriptors table
> + */
> +struct ffa_partitions {
> +       u32 count;
> +       struct ffa_partition_desc *descs; /* virtual address */
> +};
> +
> +/**
> + * struct ffa_prvdata - the driver private data structure
> + *
> + * @dev:       The arm_ffa device under u-boot driver model
> + * @ffa_ops:   The driver operations structure
> + * @fwk_version:       FF-A framework version
> + * @id:        u-boot endpoint ID
> + * @partitions:        The partitions descriptors structure
> + * @pair:      The RX/TX buffers pair
> + * @invoke_ffa_fn:     The function executing the FF-A function
> + * @features:  Table of the FF-A functions having features
> + *
> + * The driver data structure hosting all resident data.
> + */
> +struct ffa_prvdata {
> +       struct udevice *dev;
> +       struct ffa_bus_ops ffa_ops;
> +       u32 fwk_version;
> +       u16 id;
> +       struct ffa_partitions partitions;
> +       struct ffa_rxtxpair pair;
> +       invoke_ffa_fn_t invoke_ffa_fn;
> +       struct ffa_features_desc features[FFA_FEATURE_DESC_CNT];
> +};
> +
> +/**
> + * ffa_device_get - create, bind and probe the arm_ffa device
> + */
> +int ffa_device_get(void);
> +
> +/**
> + * ffa_bus_prvdata_get - bus driver private data getter
> + */
> +struct ffa_prvdata **ffa_bus_prvdata_get(void);
> +
> +#endif
> diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c
> new file mode 100644
> index 0000000000..40d140fc3e
> --- /dev/null
> +++ b/drivers/arm-ffa/core.c
> @@ -0,0 +1,1338 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include "arm_ffa_prv.h"
> +#include <asm/global_data.h>
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/device-internal.h>
> +#include <dm/devres.h>
> +#include <dm/root.h>
> +#include <linux/errno.h>
> +#include <linux/sizes.h>
> +#include <log.h>
> +#include <malloc.h>
> +#include <string.h>
> +#include <uuid.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/**
> + * The device private data structure containing all the resident
> + * data read from secure world
> + */
> +__ffa_runtime_data struct ffa_prvdata *ffa_priv_data;

I think it's better if we just keep this as efi_runtime, especially
since the rest of the declarations you use are marked as efi_*

[...]

> +
> +/**
> + * ffa_device_get - create, bind and probe the arm_ffa device
> + *
> + * This boot time function makes sure the arm_ffa device is
> + * created, bound to this driver, probed and ready to use.
> + * Arm FF-A transport is implemented through a single u-boot
> + * device managing the FF-A bus (arm_ffa).
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +int ffa_device_get(void)
> +{
> +       int ret;
> +       struct udevice *dev = NULL;
> +
> +       if (ffa_priv_data && ffa_priv_data->dev)
> +               return FFA_ERR_STAT_SUCCESS;
> +
> +       ret = device_bind(dm_root(),
> +                         DM_DRIVER_GET(arm_ffa),
> +                         FFA_DRV_NAME,
> +                         NULL,
> +                         ofnode_null(),
> +                         &dev);
> +       if (ret)
> +               return ret;
> +
> +       /* The FF-A bus discovery succeeds when probing is successful */
> +       ret = device_probe(dev);
> +       if (ret) {
> +               ffa_err("arm_ffa device probing failed");
> +               ffa_remove_device(dev);
> +               return ret;
> +       }
> +
> +       return FFA_ERR_STAT_SUCCESS;

The return values in most of the functions are confusing.  I think you
should just get rid of FFA_ERR_STAT_SUCCESS and just return 0

[...]

> +
> +       if (!ffa_priv_data->invoke_ffa_fn)
> +               panic("[FFA] no private data found\n");

Get rid of all the panicking please.  We've discussed this on a
previous email.  Isn't an error message enough?

[...]

> + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> + *                       buffers
> + *
> + * This is the boot time function that implements FFA_RXTX_MAP FF-A function
> + * to map the RX/TX buffers
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +static int ffa_map_rxtx_buffers(size_t buf_4k_pages)
> +{
> +       int ret;
> +       ffa_value_t res = {0};
> +
> +       if (!ffa_priv_data->invoke_ffa_fn)
> +               panic("[FFA] no private data found\n");
> +
> +       ret = ffa_alloc_rxtx_buffers(buf_4k_pages);
> +       if (ret != FFA_ERR_STAT_SUCCESS)
> +               return ret;
> +
> +       /*
> +        * we need to pass the physical addresses of the RX/TX buffers
> +        * in u-boot physical/virtual mapping is 1:1
> +        *no need to convert from virtual to physical
> +        */
> +
> +       ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +                       .a0 = FFA_RXTX_MAP,
> +                       .a1 = ffa_priv_data->pair.txbuf,
> +                       .a2 = ffa_priv_data->pair.rxbuf,
> +                       .a3 = buf_4k_pages,
> +                       .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> +                       }, &res);
> +
> +       switch (res.a0) {
> +       case FFA_ERROR:
> +       {

There are comments in v2 that are ignored throughout the patchset.
Please check the remarks in v2 before sending a new patchset


> +               switch (((int)res.a2)) {
> +               case FFA_ERR_STAT_INVALID_PARAMETERS:
> +                       ffa_err("One or more fields in input parameters is incorrectly encoded");
> +                       ret = -EPERM;
> +                       break;
> +               case FFA_ERR_STAT_NO_MEMORY:
> +                       ffa_err("Not enough memory");
> +                       ret = -ENOMEM;
> +                       break;
> +               case FFA_ERR_STAT_DENIED:
> +                       ffa_err("Buffer pair already registered");
> +                       ret = -EACCES;
> +                       break;
> +               case FFA_ERR_STAT_NOT_SUPPORTED:
> +                       ffa_err("This function is not implemented at this FF-A instance");
> +                       ret = -EOPNOTSUPP;
> +                       break;
> +               default:
> +                       ffa_err("Undefined error (%d)",
> +                               ((int)res.a2));
> +                       ret = -EINVAL;
> +               }
> +               break;
> +       }
> +       case FFA_SUCCESS:
> +               ffa_info("RX/TX buffers mapped");
> +               return FFA_ERR_STAT_SUCCESS;
> +       default:
> +               ffa_err("Undefined response function (0x%lx)",
> +                       res.a0);
> +               ret = -EINVAL;
> +       }
> +
> +       ffa_free_rxtx_buffers();
> +
> +       return ret;
> +}
> +
> +/**
[...]

Regards
/Ilias


> +
> +/**
> + * Declaring the arm_ffa driver under UCLASS_FFA
> + */
> +
> +U_BOOT_DRIVER(arm_ffa) = {
> +       .name           = FFA_DRV_NAME,
> +       .id             = UCLASS_FFA,
> +       .probe          = ffa_probe,
> +};
> diff --git a/drivers/arm-ffa/efi_ffa_runtime_data_mgr.c b/drivers/arm-ffa/efi_ffa_runtime_data_mgr.c
> new file mode 100644
> index 0000000000..942601a7ba
> --- /dev/null
> +++ b/drivers/arm-ffa/efi_ffa_runtime_data_mgr.c
> @@ -0,0 +1,94 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include "arm_ffa_prv.h"
> +
> +/**
> + * ffa_copy_runtime_data - copy the private data structure  to the runtime area
> + *
> + * This boot time function copies the arm_ffa driver data structures including
> + *  partitions data to the EFI runtime data section.
> + *
> + * Return:
> + *
> + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> + */
> +efi_status_t ffa_copy_runtime_data(void)
> +{
> +       efi_status_t efi_ret;
> +       efi_uintn_t prvdata_pages;
> +       efi_uintn_t descs_pages;
> +       struct ffa_prvdata **prvdata = NULL; /* Pointer to the current structure */
> +       struct ffa_prvdata *runtime_prvdata = NULL; /* Pointer to the structure runtime copy */
> +       u64 runtime_descs = 0;
> +
> +       prvdata = ffa_bus_prvdata_get();
> +
> +       printf("INFO: EFI: FFA: prv data area at 0x%llx\n", (u64)prvdata);
> +
> +       /* allocate private data runtime area */
> +
> +       prvdata_pages = efi_size_in_pages(sizeof(struct ffa_prvdata));
> +       efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> +                                    EFI_RUNTIME_SERVICES_DATA,
> +                                    prvdata_pages,
> +                                    (u64 *)&runtime_prvdata);
> +
> +       if (efi_ret != EFI_SUCCESS) {
> +               printf("ERROR: EFI: FFA: allocating runtime data (err: 0x%lx, addr 0x%llx)\n",
> +                      efi_ret, (u64)runtime_prvdata);
> +
> +               return efi_ret;
> +       }
> +
> +       printf("INFO: EFI: FFA: runtime data area at 0x%llx\n", (u64)runtime_prvdata);
> +
> +       if (!runtime_prvdata)
> +               return EFI_INVALID_PARAMETER;
> +
> +       /* allocate the partition data runtime area */
> +
> +       descs_pages = efi_size_in_pages((*prvdata)->partitions.count *
> +                                       sizeof(struct ffa_partition_desc));
> +       efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> +                                    EFI_RUNTIME_SERVICES_DATA,
> +                                    descs_pages,
> +                                    &runtime_descs);
> +
> +       if (efi_ret != EFI_SUCCESS) {
> +               printf("ERROR: EFI: FFA: allocating runtime SPs data (err: 0x%lx, addr 0x%llx)\n",
> +                      efi_ret, runtime_descs);
> +
> +               efi_free_pages((u64)runtime_prvdata, prvdata_pages);
> +
> +               return efi_ret;
> +       }
> +
> +       printf("INFO: EFI: FFA: SPs runtime area at 0x%llx\n", (u64)runtime_descs);
> +
> +       if (!runtime_descs)
> +               return EFI_INVALID_PARAMETER;
> +
> +       *runtime_prvdata = **prvdata;
> +
> +       runtime_prvdata->dev = NULL;
> +       runtime_prvdata->ffa_ops.partition_info_get = NULL;
> +       runtime_prvdata->ffa_ops.rxtx_unmap = NULL;
> +       runtime_prvdata->partitions.descs = (struct ffa_partition_desc *)runtime_descs;
> +       runtime_prvdata->pair.rxbuf = 0;
> +       runtime_prvdata->pair.txbuf = 0;
> +
> +       /*
> +        * Update the private data structure pointer in the driver
> +        * no need to free the old structure. devm takes care of that
> +        */
> +       *prvdata = runtime_prvdata;
> +
> +       printf("INFO: EFI: FFA: runtime prv data now at 0x%llx , SPs count %d\n",
> +              (u64)*prvdata, (*prvdata)->partitions.count);
> +
> +       return FFA_ERR_STAT_SUCCESS;
> +}
> diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> new file mode 100644
> index 0000000000..ee9ce2d99d
> --- /dev/null
> +++ b/include/arm_ffa.h
> @@ -0,0 +1,132 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#ifndef __ARM_FFA_H
> +#define __ARM_FFA_H
> +
> +#include <linux/printk.h>
> +
> +/*
> + * This header is public. It can be used by clients to access
> + * data structures and definitions they need
> + */
> +
> +/*
> + * Macros for displaying logs
> + */
> +
> +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> +
> +/*
> + * The driver operations success error code
> + */
> +#define FFA_ERR_STAT_SUCCESS                           (0)
> +
> +/*
> + * struct ffa_partition_info - Partition information descriptor
> + * @id:        Partition ID
> + * @exec_ctxt: Execution context count
> + * @properties:        Partition properties
> + *
> + * Data structure containing information about partitions instantiated in the system
> + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> + */
> +struct  __packed ffa_partition_info {
> +       u16 id;
> +       u16 exec_ctxt;
> +/* partition supports receipt of direct requests */
> +#define FFA_PARTITION_DIRECT_RECV      BIT(0)
> +/* partition can send direct requests. */
> +#define FFA_PARTITION_DIRECT_SEND      BIT(1)
> +/* partition can send and receive indirect messages. */
> +#define FFA_PARTITION_INDIRECT_MSG     BIT(2)
> +       u32 properties;
> +};
> +
> +/*
> + * struct ffa_send_direct_data - Data structure hosting the data
> + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * @data0-4:   Data read/written from/to x3-x7 registers
> + *
> + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> + * or read from FFA_MSG_SEND_DIRECT_RESP
> + */
> +
> +/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
> +struct __packed ffa_send_direct_data {
> +       unsigned long data0; /* w3/x3 */
> +       unsigned long data1; /* w4/x4 */
> +       unsigned long data2; /* w5/x5 */
> +       unsigned long data3; /* w6/x6 */
> +       unsigned long data4; /* w7/x7 */
> +};
> +
> +#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
> +
> +#include <efi_loader.h>
> +
> +/*
> + *  __ffa_runtime - controls whether functions are
> + * available after calling the EFI ExitBootServices service.
> + * Functions tagged with these keywords are resident (available at boot time and
> + * at runtime)
> + */
> +
> +#define __ffa_runtime_data __efi_runtime_data
> +#define __ffa_runtime __efi_runtime
> +
> +#else
> +
> +/*
> + *  The FF-A driver is independent from EFI
> + */
> +
> +#define __ffa_runtime_data
> +#define __ffa_runtime
> +
> +#endif
> +
> +/**
> + * struct ffa_bus_ops - The driver operations structure
> + * @partition_info_get:        callback for the FFA_PARTITION_INFO_GET
> + * @sync_send_receive: callback for the FFA_MSG_SEND_DIRECT_REQ
> + * @rxtx_unmap:        callback for the FFA_RXTX_UNMAP
> + *
> + * The data structure providing all the operations supported by the driver.
> + * This structure is EFI runtime resident.
> + */
> +struct ffa_bus_ops {
> +       int (*partition_info_get)(const char *uuid_str,
> +                                 u32 *parts_size, struct ffa_partition_info *buffer);
> +       int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg);
> +       int (*rxtx_unmap)(void);
> +};
> +
> +/**
> + * The device driver and the Uclass driver public functions
> + */
> +
> +/**
> + * ffa_bus_ops_get - driver operations getter
> + */
> +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
> + */
> +int ffa_bus_discover(void);
> +
> +#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
> +
> +/**
> + * ffa_copy_runtime_data - copy the private data structure and the SPs data to the runtime area
> + */
> +efi_status_t ffa_copy_runtime_data(void);
> +
> +#endif
> +
> +#endif
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index a432e43871..6eebbe9c7d 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -55,6 +55,7 @@ enum uclass_id {
>         UCLASS_EFI_MEDIA,       /* Devices provided by UEFI firmware */
>         UCLASS_ETH,             /* Ethernet device */
>         UCLASS_ETH_PHY,         /* Ethernet PHY device */
> +       UCLASS_FFA,             /* Arm Firmware Framework for Armv8-A */
>         UCLASS_FIRMWARE,        /* Firmware */
>         UCLASS_FUZZING_ENGINE,  /* Fuzzing engine */
>         UCLASS_FS_FIRMWARE_LOADER,              /* Generic loader */
> diff --git a/include/uuid.h b/include/uuid.h
> index 4a4883d3b5..789f8e0f15 100644
> --- a/include/uuid.h
> +++ b/include/uuid.h
> @@ -44,4 +44,12 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
>  const char *uuid_guid_get_str(const unsigned char *guid_bin);
>  void gen_rand_uuid(unsigned char *uuid_bin);
>  void gen_rand_uuid_str(char *uuid_str, int str_format);
> +
> +#ifdef CONFIG_ARM_FFA_TRANSPORT
> +/**
> + * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
> + */
> +int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin);
> +#endif
> +
>  #endif
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index 4da64b5d29..e02bb445f5 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -23,6 +23,10 @@
>  #include <asm/setjmp.h>
>  #include <linux/libfdt_env.h>
>
> +#if defined(CONFIG_ARM_FFA_TRANSPORT)
> +#include <arm_ffa.h>
> +#endif
> +
>  DECLARE_GLOBAL_DATA_PTR;
>
>  /* Task priority level */
> @@ -2113,6 +2117,10 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
>         struct efi_event *evt, *next_event;
>         efi_status_t ret = EFI_SUCCESS;
>
> +#if defined(CONFIG_ARM_FFA_TRANSPORT)
> +       int ffa_ret;
> +#endif
> +
>         EFI_ENTRY("%p, %zx", image_handle, map_key);
>
>         /* Check that the caller has read the current memory map */
> @@ -2173,6 +2181,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
>                 dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
>         }
>
> +#if defined(CONFIG_ARM_FFA_TRANSPORT)
> +       /* unmap FF-A RX/TX buffers */
> +       ffa_ret = ffa_bus_ops_get()->rxtx_unmap();
> +       if (ffa_ret)
> +               debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n");
> +       else
> +               debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
> +#endif
> +
>         /* Patch out unsupported runtime function */
>         efi_runtime_detach();
>
> diff --git a/lib/uuid.c b/lib/uuid.c
> index 284f8113ff..50b3e61d59 100644
> --- a/lib/uuid.c
> +++ b/lib/uuid.c
> @@ -1,6 +1,7 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  /*
>   * Copyright 2011 Calxeda, Inc.
> + * Copyright 2022 ARM Limited
>   */
>
>  #include <common.h>
> @@ -342,6 +343,70 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
>         return 0;
>  }
>
> +#ifdef CONFIG_ARM_FFA_TRANSPORT
> +/**
> + * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
> + * @uuid_str:  UUID string in big endian format (36 bytes wide + '/0')
> + * @uuid_bin:  preallocated 16 bytes UUID buffer in little endian format
> + *
> + * UUID string is 36 characters (36 bytes):
> + *
> + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
> + * be               be      be       be      be
> + *
> + * where x is a hexadecimal character. Fields are separated by '-'s.
> + * When converting to a binary UUID, these endianness rules apply:
> + *     be: means the field in the string is considered a big endian hex number
> + *        and should be converted to little endian binary format
> + *
> + * Return:
> + *
> + *    uuid_bin filled with little endian UUID data
> + *    On success 0 is returned. Otherwise, failure code.
> + */
> +int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin)
> +{
> +       u16 tmp16 = 0;
> +       u32 tmp32 = 0;
> +       u64 tmp64 = 0;
> +
> +       if (!uuid_str_valid(uuid_str) || !uuid_bin)
> +               return -EINVAL;
> +
> +       /*
> +        * reverse bytes from big to little endian
> +        */
> +       tmp32 = simple_strtoul(uuid_str, NULL, 16);
> +       memcpy(uuid_bin, &tmp32, 4);
> +
> +       /*
> +        * reverse bytes from big to little endian
> +        */
> +       tmp16 = simple_strtoul(uuid_str + 9, NULL, 16);
> +       memcpy(uuid_bin + 4, &tmp16, 2);
> +
> +       /*
> +        * reverse bytes from big to little endian
> +        */
> +       tmp16 = simple_strtoul(uuid_str + 14, NULL, 16);
> +       memcpy(uuid_bin + 6, &tmp16, 2);
> +
> +       /*
> +        * reverse bytes from big to little endian
> +        */
> +       tmp16 = simple_strtoul(uuid_str + 19, NULL, 16);
> +       memcpy(uuid_bin + 8, &tmp16, 2);
> +
> +       /*
> +        * reverse bytes from big to little endian
> +        */
> +       tmp64 = simple_strtoull(uuid_str + 24, NULL, 16);
> +       memcpy(uuid_bin + 10, (char *)&tmp64, 6);
> +
> +       return 0;
> +}
> +#endif
> +
>  /*
>   * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
>   *
> --
> 2.17.1
>

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver
  2022-08-01 17:20                               ` [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
  2022-08-12  7:39                                 ` Ilias Apalodimas
@ 2022-08-13  2:21                                 ` Simon Glass
  2022-09-26 11:37                                   ` Abdellatif El Khlifi
  2022-11-15 15:24                                 ` Simon Glass
  2 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2022-08-13  2:21 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Ilias Apalodimas, Jens Wiklander, achin.gupta, Tom Rini,
	U-Boot Mailing List, vishnu.banavath, xueliang.zhong, nd

Hi Abdellatif,

On Mon, 1 Aug 2022 at 11:21, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
>
> The Firmware Framework for Arm A-profile processors (FF-A)
> describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World leveraging TrustZone
> technology.
>
> This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> querying the FF-A framework from the secure world.
>
> 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
>
> In u-boot FF-A design, FF-A is considered as a discoverable bus.
> The Secure World is considered as one entity to communicate with
> using the FF-A bus. FF-A communication is handled by one device and
> one instance (the bus). This FF-A driver takes care of all the
> interactions between Normal world and Secure World.
>
> The driver exports its operations to be used by upper layers.
>
> Exported operations:
>
> - partition_info_get
> - sync_send_receive
> - rxtx_unmap
>
> This implementation provides an optional feature to copy the driver data
> to EFI runtime area.

This is v2 but I don't see a change list?

>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Cc: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  MAINTAINERS                                |    6 +
>  common/board_r.c                           |    7 +
>  drivers/Kconfig                            |    2 +
>  drivers/Makefile                           |    1 +
>  drivers/arm-ffa/Kconfig                    |   33 +
>  drivers/arm-ffa/Makefile                   |    7 +
>  drivers/arm-ffa/arm-ffa-uclass.c           |   16 +
>  drivers/arm-ffa/arm_ffa_prv.h              |  219 ++++
>  drivers/arm-ffa/core.c                     | 1338 ++++++++++++++++++++
>  drivers/arm-ffa/efi_ffa_runtime_data_mgr.c |   94 ++
>  include/arm_ffa.h                          |  132 ++
>  include/dm/uclass-id.h                     |    1 +
>  include/uuid.h                             |    8 +
>  lib/efi_loader/efi_boottime.c              |   17 +
>  lib/uuid.c                                 |   65 +
>  15 files changed, 1946 insertions(+)
>  create mode 100644 drivers/arm-ffa/Kconfig
>  create mode 100644 drivers/arm-ffa/Makefile
>  create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
>  create mode 100644 drivers/arm-ffa/core.c
>  create mode 100644 drivers/arm-ffa/efi_ffa_runtime_data_mgr.c
>  create mode 100644 include/arm_ffa.h
>

I think this should be in an existing directory, or perhaps drivers/firmware.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v3 2/4] arm64: smccc: clear the Xn registers after SMC calls
  2022-08-01 17:20                               ` [PATCH v3 2/4] arm64: smccc: clear the Xn registers after " Abdellatif El Khlifi
@ 2022-08-16 11:48                                 ` Jens Wiklander
  2022-09-26 11:33                                   ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Jens Wiklander @ 2022-08-16 11:48 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: ilias.apalodimas, achin.gupta, trini, u-boot, vishnu.banavath,
	xueliang.zhong, nd

On Mon, Aug 1, 2022 at 7:21 PM Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> set to zero the x0-x17 registers
>
> As per the SMCCC v1.2 spec, unused result and scratch registers can leak
> information after an SMC call. We can mitigate against this risk by
> returning zero in each register.
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Cc: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  arch/arm/cpu/armv8/smccc-call.S | 20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
>
> diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
> index ec6f299bc9..8ac3e461e4 100644
> --- a/arch/arm/cpu/armv8/smccc-call.S
> +++ b/arch/arm/cpu/armv8/smccc-call.S
> @@ -84,6 +84,26 @@ ENDPROC(__arm_smccc_hvc)
>         stp     x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
>         stp     x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
>
> +       /* x0-x17 registers can leak information after an SMC or HVC call. Let's clear them */
> +       mov     x0, xzr
> +       mov     x1, xzr
> +       mov     x2, xzr
> +       mov     x3, xzr
> +       mov     x4, xzr
> +       mov     x5, xzr
> +       mov     x6, xzr
> +       mov     x7, xzr
> +       mov     x8, xzr
> +       mov     x9, xzr
> +       mov     x10, xzr
> +       mov     x11, xzr
> +       mov     x12, xzr
> +       mov     x13, xzr
> +       mov     x14, xzr
> +       mov     x15, xzr
> +       mov     x16, xzr
> +       mov     x17, xzr
> +

Is this information leakage worse than the information leakage from an
ordinary C function?
My point is, is this needed?

Thanks,
Jens

>         /* Restore original x19 */
>         ldp     xzr, x19, [sp], #16
>         ret
> --
> 2.17.1
>

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v4 00/10] introduce Arm FF-A support
  2022-08-01 17:20                             ` [PATCH v3 0/4] " Abdellatif El Khlifi
                                                 ` (3 preceding siblings ...)
  2022-08-01 17:20                               ` [PATCH v3 4/4] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2022-09-26 10:17                               ` Abdellatif El Khlifi
  2022-09-26 10:17                                 ` [PATCH v4 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                   ` (10 more replies)
  4 siblings, 11 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 10:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, ilias.apalodimas, jens.wiklander, trini, sjg,
	vishnu.banavath, xueliang.zhong, achin.gupta, nd, Xueliang Zhong

This new version of the patchset provides improvements to the FF-A
support and updates for the Sandbox test cases.

Please refer to the changelog below for a list of the major changes
made.

Please refer to the changelog in the commit logs for a detailed view
of the changes including the minor changes.

All previous review comments have been addressed. 

I'll reply to the individual review comments after the submission
of this v4 patchset.

Please find at [4] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of the major changes:
===========================

v4:

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/bind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: example of boot logs when enabling FF-A

```
U-Boot 2022.07 (Jul 11 2022 - 13:42:58 +0000) corstone1000 aarch64 
...
[FFA] Conduit is SMC
[FFA] FF-A driver 1.0
FF-A framework 1.0
[FFA] Versions are compatible 
[FFA] endpoint ID is 0
[FFA] Using 1 4KB page(s) for RX/TX buffers size
[FFA] RX buffer at virtual address 0xfdf18000
[FFA] TX buffer at virtual address 0xfdf1a000
[FFA] RX/TX buffers mapped
[FFA] Reading partitions data from the RX buffer
[FFA] Partition ID 8001 : info cached
[FFA] Partition ID 8002 : info cached
[FFA] Partition ID 8003 : info cached
[FFA] 3 partition(s) found and cached
Hit any key to stop autoboot:  0 
...
[FFA] Preparing for checking partitions count
[FFA] Searching partitions using the provided UUID
[FFA] No partition found. Querying framework ...
[FFA] Reading partitions data from the RX buffer
[FFA] Number of partition(s) found matching the UUID: 1
EFI: Pre-allocating 1 partition(s) info structures
[FFA] Preparing for filling partitions info
[FFA] Searching partitions using the provided UUID
[FFA] Partition ID 8003 matches the provided UUID
EFI: MM partition ID 0x8003
...
EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from configuration table
EFI stub: Exiting boot services...
[FFA] Freeing RX/TX buffers
INFO: EFI: FFA: prv data area at 0xfff2f768
INFO: EFI: FFA: runtime data area at 0xfcef4000
INFO: EFI: FFA: SPs runtime area at 0xfcef3000
INFO: EFI: FFA: runtime prv data now at 0xfcef4000 , SPs count 3
INFO: EFI: FFA: runtime data copied
Booting Linux on physical CPU 0x0000000000 [0x410fd040]
```

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>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Vishnu Banavath <vishnu.banavath@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (10):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  arm64: smccc: clear the Xn registers after SMC calls
  lib: uuid: introduce be_uuid_str_to_le_bin function
  arm_ffa: introduce Arm FF-A low-level driver
  arm_ffa: introduce armffa command
  arm_ffa: introduce the FF-A Sandbox driver
  arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: introduce FF-A MM communication
  arm_ffa: corstone1000: enable EFI MM communication

 MAINTAINERS                                   |   11 +
 arch/arm/cpu/armv8/cache.S                    |   19 +
 arch/arm/cpu/armv8/cache_v8.c                 |    6 +-
 arch/arm/cpu/armv8/smccc-call.S               |   62 +
 arch/arm/lib/asm-offsets.c                    |   14 +
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    2 +
 cmd/armffa.c                                  |  242 +++
 common/board_r.c                              |    9 +
 configs/corstone1000_defconfig                |    4 +
 configs/sandbox64_defconfig                   |    2 +
 configs/sandbox_defconfig                     |    2 +
 doc/README.ffa.drv                            |  160 ++
 doc/arch/sandbox.rst                          |    1 +
 drivers/Kconfig                               |    2 +
 drivers/Makefile                              |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   46 +
 drivers/firmware/arm-ffa/Makefile             |    8 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     |   16 +
 drivers/firmware/arm-ffa/arm_ffa_prv.h        |  201 +++
 drivers/firmware/arm-ffa/core.c               | 1358 +++++++++++++++++
 .../arm-ffa/efi_ffa_runtime_data_mgr.c        |   94 ++
 drivers/firmware/arm-ffa/sandbox.c            |  659 ++++++++
 .../firmware/arm-ffa/sandbox_arm_ffa_prv.h    |  144 ++
 include/arm_ffa.h                             |  127 ++
 include/configs/corstone1000.h                |    9 +
 include/dm/uclass-id.h                        |    4 +
 include/linux/arm-smccc.h                     |   43 +
 include/mm_communication.h                    |    9 +-
 include/sandbox_arm_ffa.h                     |   91 ++
 include/uuid.h                                |    8 +
 lib/efi_loader/Kconfig                        |   14 +-
 lib/efi_loader/efi_boottime.c                 |   22 +
 lib/efi_loader/efi_variable_tee.c             |  263 +++-
 lib/uuid.c                                    |   64 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   40 +
 test/dm/Makefile                              |    2 +
 test/dm/ffa.c                                 |  394 +++++
 39 files changed, 4156 insertions(+), 9 deletions(-)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/README.ffa.drv
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/firmware/arm-ffa/core.c
 create mode 100644 drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
 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/arm_ffa.h
 create mode 100644 include/sandbox_arm_ffa.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v4 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
@ 2022-09-26 10:17                                 ` Abdellatif El Khlifi
  2022-09-26 10:17                                 ` [PATCH v4 02/10] arm64: smccc: clear the Xn registers after SMC calls Abdellatif El Khlifi
                                                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 10:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, ilias.apalodimas, jens.wiklander, trini, sjg,
	vishnu.banavath, xueliang.zhong, achin.gupta, nd

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Changelog:
===============

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

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>
---
 arch/arm/cpu/armv8/smccc-call.S | 53 +++++++++++++++++++++++++++++++++
 arch/arm/lib/asm-offsets.c      | 14 +++++++++
 include/linux/arm-smccc.h       | 43 ++++++++++++++++++++++++++
 3 files changed, 110 insertions(+)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..ec6f299bc9 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
@@ -45,3 +47,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 22fd541f9a..1bc2d90faa 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,9 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -117,6 +120,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+	#ifdef CONFIG_ARM64
+		DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+		DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+		DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+		DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+		DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+		DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+		DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+		DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+		DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+	#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..9105031d55 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +72,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v4 02/10] arm64: smccc: clear the Xn registers after SMC calls
  2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2022-09-26 10:17                                 ` [PATCH v4 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2022-09-26 10:17                                 ` Abdellatif El Khlifi
  2022-09-26 10:17                                 ` [PATCH v4 03/10] lib: uuid: introduce be_uuid_str_to_le_bin function Abdellatif El Khlifi
                                                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 10:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, ilias.apalodimas, jens.wiklander, trini, sjg,
	vishnu.banavath, xueliang.zhong, achin.gupta, nd

set to zero the x0-x17 registers

As per the SMCCC v1.2 spec, unused result and scratch registers
can leak information after an SMC call. We can mitigate against
this risk by returning zero in each register.

The leakage we are referring to is data leakage across exception
levels. The intent is to prevent lower exception levels (EL1/EL0)
from reading the SMC data exchanged at EL2.

Changelog:
===============

v4:

* move the clearing code into a new macro: clear_gp_regs

v3:

* clear the Xn registers after SMC calls

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>
---
 arch/arm/cpu/armv8/smccc-call.S | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index ec6f299bc9..32f3eb8eeb 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -50,6 +50,12 @@ ENDPROC(__arm_smccc_hvc)
 
 #ifdef CONFIG_ARM64
 
+	.macro	clear_gp_regs
+	.irp	n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17
+	mov	x\n, xzr
+	.endr
+	.endm
+
 	.macro SMCCC_1_2 instr
 	/* Save `res` and free a GPR that won't be clobbered */
 	stp     x1, x19, [sp, #-16]!
@@ -84,6 +90,9 @@ ENDPROC(__arm_smccc_hvc)
 	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
 	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
 
+	/* x0-x17 registers can leak information after an SMC or HVC call. Let's clear them */
+	clear_gp_regs
+
 	/* Restore original x19 */
 	ldp     xzr, x19, [sp], #16
 	ret
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v4 03/10] lib: uuid: introduce be_uuid_str_to_le_bin function
  2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2022-09-26 10:17                                 ` [PATCH v4 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2022-09-26 10:17                                 ` [PATCH v4 02/10] arm64: smccc: clear the Xn registers after SMC calls Abdellatif El Khlifi
@ 2022-09-26 10:17                                 ` Abdellatif El Khlifi
  2022-09-26 10:17                                 ` [PATCH v4 04/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
                                                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 10:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, ilias.apalodimas, jens.wiklander, trini, sjg,
	vishnu.banavath, xueliang.zhong, achin.gupta, nd

convert big endian UUID string to little endian buffer

Changelog:
===============

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

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>
---
 include/uuid.h |  8 +++++++
 lib/uuid.c     | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..ad3af350f9 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,8 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +46,10 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * be_uuid_str_to_le_bin - Converts a big endian UUID string to a little endian buffer
+ */
+int be_uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 465e1ac38f..15a9ab49d5 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -346,6 +348,68 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * be_uuid_str_to_le_bin - Converts a big endian UUID string to a little endian buffer
+ * @uuid_str:	UUID string in big endian format (36 bytes wide + '/0')
+ * @uuid_bin:	preallocated 16 bytes UUID buffer in little endian format
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ * be		     be	     be	      be      be
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a binary UUID, these endianness rules apply:
+ *     be: means the field in the string is considered a big endian hex number
+ *	   and should be converted to little endian binary format
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int be_uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16 = 0;
+	u32 tmp32 = 0;
+	u64 tmp64 = 0;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp32 = simple_strtoul(uuid_str, NULL, 16);
+	memcpy(uuid_bin, &tmp32, 4);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 9, NULL, 16);
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 14, NULL, 16);
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 19, NULL, 16);
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp64 = simple_strtoull(uuid_str + 24, NULL, 16);
+	memcpy(uuid_bin + 10, (char *)&tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v4 04/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                   ` (2 preceding siblings ...)
  2022-09-26 10:17                                 ` [PATCH v4 03/10] lib: uuid: introduce be_uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2022-09-26 10:17                                 ` Abdellatif El Khlifi
  2022-09-26 10:17                                 ` [PATCH v4 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 10:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, ilias.apalodimas, jens.wiklander, trini, sjg,
	vishnu.banavath, xueliang.zhong, achin.gupta, nd

Add the driver implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
and FFA_MSG_SEND_DIRECT_{REQ, RESP}.

In u-boot FF-A design, FF-A is considered as a discoverable bus.
The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- partition_info_get
- sync_send_receive
- rxtx_unmap

This implementation provides an optional feature to copy the driver data
to EFI runtime area.

[1]: https://developer.arm.com/documentation/den0077/latest/

Changelog:
===============

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_bind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the u-boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

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>
---
 MAINTAINERS                                   |    7 +
 common/board_r.c                              |    9 +
 doc/README.ffa.drv                            |  160 ++
 drivers/Kconfig                               |    2 +
 drivers/Makefile                              |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   39 +
 drivers/firmware/arm-ffa/Makefile             |    7 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     |   16 +
 drivers/firmware/arm-ffa/arm_ffa_prv.h        |  196 +++
 drivers/firmware/arm-ffa/core.c               | 1344 +++++++++++++++++
 .../arm-ffa/efi_ffa_runtime_data_mgr.c        |   94 ++
 include/arm_ffa.h                             |  127 ++
 include/dm/uclass-id.h                        |    4 +
 lib/efi_loader/efi_boottime.c                 |   15 +
 14 files changed, 2021 insertions(+)
 create mode 100644 doc/README.ffa.drv
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/firmware/arm-ffa/core.c
 create mode 100644 drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
 create mode 100644 include/arm_ffa.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 83346183ee..02b84d5074 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -248,6 +248,13 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	doc/README.ffa.drv
+F:	drivers/firmware/arm-ffa/
+F:	include/arm_ffa.h
+
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/common/board_r.c b/common/board_r.c
index 56eb60fa27..8c99faddfd 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -7,6 +7,8 @@
  * (C) Copyright 2002
  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2022 ARM Limited
  */
 
 #include <common.h>
@@ -66,6 +68,10 @@
 #include <efi_loader.h>
 #include <relocate.h>
 
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+#include <arm_ffa.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -770,6 +776,9 @@ static init_fnc_t init_sequence_r[] = {
 	INIT_FUNC_WATCHDOG_RESET
 	initr_net,
 #endif
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+	ffa_bus_discover,
+#endif
 #ifdef CONFIG_POST
 	initr_post,
 #endif
diff --git a/doc/README.ffa.drv b/doc/README.ffa.drv
new file mode 100644
index 0000000000..1c0a33deb8
--- /dev/null
+++ b/doc/README.ffa.drv
@@ -0,0 +1,160 @@
+Arm FF-A Driver
+====================
+
+Introduction
+--------------------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software sandboxes to communicate with each other. A sandbox aka partition could
+be a VM in the Normal or Secure world, an application in S-EL0, or a Trusted OS in S-EL1.
+
+This FF-A driver implements the interfaces to communicate with partitions in the Secure world aka Secure partitions (SPs).
+
+The driver specifically focuses on communicating with SPs that isolate portions of EFI runtime services that must run in a
+protected environment which is inaccessible by the Host OS or Hypervisor. Examples of such services are set/get variables.
+
+FF-A driver uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest.
+- Access an SP's service through communication protocols e.g. EFI MM communication protocol.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the driver relies on FF-A specification v1.0 and uses SMC32 calling convention.
+
+The driver has been tested with Optee OS which supports SMC32 for most of the SMC ABIs.
+
+For more details please refer to: https://developer.arm.com/documentation/den0077/a/?lang=en
+
+The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
+
+For more details please refer to: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+CONFIG_ARM_FFA_TRANSPORT
+    Enables the FF-A bus driver. Turn this on if you want to use FF-A communication.
+
+CONFIG_ARM_FFA_EFI_RUNTIME_MODE
+    Optional config that enables EFI runtime support for FF-A data and code.
+    ffa_copy_runtime_data allows to copy the FF-A driver data structures to EFI runtime data section.
+    Turning the config on makes ffa_copy_runtime_data available for use and the driver code placed at EFI runtime code section.
+    Call ffa_copy_runtime_data at the event on which you want the FF-A data to be copied (example: at ExitBootServices).
+
+CONFIG_SANDBOX_FFA
+    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under Sandbox and provides
+    functional tests for FF-A.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the expected arguments from the ABI.
+
+The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is giving back to the u-boot FF-A driver (non secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs in the driver.
+
+FF-A bus discovery in u-boot
+-------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is automatically discovered at initcall level (after u-boot relocation).
+
+The function that triggers the discovery process is ffa_bus_discover.
+
+ffa_bus_discover creates, binds and probes the arm_ffa device using device_{bind, probe} APIs.
+
+When the device is probed, ffa_probe is called which tries to communicate with the secure world or hypervisor.
+
+The FF-A bus is usable when these checks succeed:
+
+- querying the FF-A framework version
+- querying from secure world the u-boot endpoint ID
+- querying from secure world the supported features of the specified FF-A calls
+- mapping the RX/TX buffers
+- querying from secure world all the partitions information
+
+Probing fails when any of these operations fail. The FF-A bus discovery succeeds when probing is successful.
+
+When discovery fails the arm_ffa device is destroyed.
+
+The bus driver layer
+------------------------------
+
+The driver comes on top of the SMCCC layer and is implemented in drivers/firmware/arm-ffa/core.c
+
+The driver provides the following features:
+
+- Support for the 32-bit version of the following ABIs:
+
+FFA_VERSION
+FFA_ID_GET
+FFA_FEATURES
+FFA_PARTITION_INFO_GET
+FFA_RXTX_UNMAP
+FFA_RX_RELEASE
+FFA_RUN
+FFA_ERROR
+FFA_SUCCESS
+FFA_INTERRUPT
+
+- Support for the 64-bit version of the following ABIs:
+
+FFA_RXTX_MAP
+FFA_MSG_SEND_DIRECT_REQ
+FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper layers focus on exchanged data,
+the driver takes care of how to transport that to the secure world/hypervisor using FF-A.
+
+- The driver provides callbacks to be used by clients to access the FF-A bus:
+
+partition_info_get
+sync_send_receive
+rxtx_unmap
+
+- FF-A bus discovery at initcalls level (after u-boot relocation). The bus is up and running if the FF-A framework is responsive and compatible with the driver.
+
+- When EFI is enabled, unmap the RX/TX buffers at ExitBootServices() level.
+
+- When CONFIG_ARM_FFA_EFI_RUNTIME_MODE enabled, ffa_copy_runtime_data function is available for use.
+
+Using armffa command
+-----------------------------------
+
+armffa is a command showcasing how to use the FF-A driver and how to invoke its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
+
+Usage:
+
+armffa <sub-command> <arguments>
+
+sub-commands:
+
+        getpart <partition UUID>
+
+            lists the partition(s) info
+
+        ping <partition ID>
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays the arm_ffa device info
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 8b6fead351..b06b1ae481 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
 
 source "drivers/adc/Kconfig"
 
+source "drivers/firmware/arm-ffa/Kconfig"
+
 source "drivers/ata/Kconfig"
 
 source "drivers/axi/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index eba9940231..c3bfad94ac 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -110,6 +110,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..aceb61cf49
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  This driver is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In u-boot FF-A design, FF-A is considered as a discoverable bus.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  This FF-A driver takes care of all the interactions between Normal world
+	  and Secure World.
+
+	  For more details about the FF-A driver, please refer to doc/README.ffa.drv
+
+config ARM_FFA_EFI_RUNTIME_MODE
+	bool "Enable EFI runtime support for FF-A data and code"
+	depends on ARM_FFA_TRANSPORT && EFI_LOADER
+	help
+	  Allows FF-A driver data structures and code to be accessible at EFI runtime.
+	  FF-A data is copied by ffa_copy_runtime_data function.
+	  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.
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..0b9b0a61b4
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+#
+
+obj-y += arm-ffa-uclass.o core.o
+obj-$(CONFIG_ARM_FFA_EFI_RUNTIME_MODE) += efi_ffa_runtime_data_mgr.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..7d9695d289
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+UCLASS_DRIVER(ffa) = {
+	.name		= "ffa",
+	.id		= UCLASS_FFA,
+};
diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
new file mode 100644
index 0000000000..7bc90f7f66
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <arm_ffa.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/arm-smccc.h>
+
+/*
+ * This header is private. It is exclusively used by the FF-A driver
+ */
+
+/* FF-A core driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* FF-A driver version definitions */
+
+#define MAJOR_VERSION_MASK		GENMASK(30, 16)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/*
+ * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
+ */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR					= 0x60,
+	FFA_SUCCESS					= 0x61,
+	FFA_INTERRUPT				= 0x62,
+	FFA_VERSION					= 0x63,
+	FFA_FEATURES				= 0x64,
+	FFA_RX_RELEASE				= 0x65,
+	FFA_RXTX_MAP				= 0x66,
+	FFA_RXTX_UNMAP			= 0x67,
+	FFA_PARTITION_INFO_GET		= 0x68,
+	FFA_ID_GET					= 0x69,
+	FFA_RUN						= 0x6D,
+	FFA_MSG_SEND_DIRECT_REQ	= 0x6F,
+	FFA_MSG_SEND_DIRECT_RESP	= 0x70,
+
+	/* to be updated when adding new FFA IDs */
+	FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
+	FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
+};
+
+/* number of the errors supported by the FF-A specification */
+#define MAX_NUMBER_FFA_ERR 9
+
+/* container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#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
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Data structure hosting the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	u64 rxbuf; /* virtual address */
+	u64 txbuf; /* virtual address */
+	size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * This data structure contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* virtual address */
+};
+
+/**
+ * struct ffa_prvdata - the driver private data structure
+ *
+ * @dev:	The arm_ffa device under u-boot driver model
+ * @ffa_ops:	The driver operations structure
+ * @fwk_version:	FF-A framework version
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ * @invoke_ffa_fn:	The function executing the FF-A function
+ *
+ * The driver data structure hosting all resident data.
+ */
+struct ffa_prvdata {
+	struct udevice *dev;
+	struct ffa_bus_ops ffa_ops;
+	u32 fwk_version;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+	invoke_ffa_fn_t invoke_ffa_fn;
+};
+
+/**
+ * ffa_device_get - create, bind and probe the arm_ffa device
+ */
+int ffa_device_get(void);
+
+/**
+ * ffa_bus_prvdata_get - bus driver private data getter
+ */
+struct ffa_prvdata **ffa_bus_prvdata_get(void);
+
+#endif
diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
new file mode 100644
index 0000000000..41c7b96e68
--- /dev/null
+++ b/drivers/firmware/arm-ffa/core.c
@@ -0,0 +1,1344 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include "arm_ffa_prv.h"
+#include <asm/global_data.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * The device private data structure containing all the resident
+ * data read from secure world
+ */
+__ffa_runtime_data struct ffa_prvdata *ffa_priv_data;
+
+/* Error mapping declarations */
+
+__ffa_runtime_data int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	0,
+	-EOPNOTSUPP,	/* NOT_SUPPORTED */
+	-EINVAL,	/* INVALID_PARAMETERS */
+	-ENOMEM,	/* NO_MEMORY */
+	-EBUSY,		/* BUSY */
+	-EINTR,		/* INTERRUPTED */
+	-EACCES,	/* DENIED */
+	-EAGAIN,	/* RETRY */
+	-ECANCELED,	/* ABORTED */
+};
+
+struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			"",
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+			"", /* INVALID_PARAMETERS */
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"", /* DENIED */
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			"",
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			"", /* INVALID_PARAMETERS */
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"", /* DENIED */
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			"",
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+			"", /* INVALID_PARAMETERS */
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"", /* DENIED */
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			"",
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			"BUSY: RX buffer of the caller is not free",
+			"", /* INTERRUPTED */
+			"DENIED: Callee is not in a state to handle this request",
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+			{
+			"",
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"", /* DENIED */
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+			{
+			"",
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			"", /* INVALID_PARAMETERS */
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"DENIED: Caller did not have ownership of the RX buffer",
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+			{
+			"",
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			"NO_MEMORY: Not enough memory",
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"DENIED: Buffer pair already registered",
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This runtime function maps the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+__ffa_runtime int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This boot time function maps the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str || !err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/*
+ * Driver core functions
+ */
+
+/**
+ * ffa_remove_device - removes the arm_ffa device
+ * @dev:	the device to be removed
+ *
+ * This boot time function makes sure the arm_ffa device is removed
+ * No need to free the kmalloced data when the device is destroyed.
+ * It's automatically done by devm management by
+ * device_remove() -> device_free() -> devres_release_probe().
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_remove_device(struct udevice *dev)
+{
+	int ret;
+
+	if (!dev) {
+		ffa_err("no udevice found");
+		return -ENODEV;
+	}
+
+	ret = device_remove(dev, DM_REMOVE_NORMAL);
+	if (ret) {
+		ffa_err("unable to remove. err:%d\n", ret);
+		return ret;
+	}
+
+	ffa_info("device removed and freed");
+
+	ret = device_unbind(dev);
+	if (ret) {
+		ffa_err("unable to unbind. err:%d\n", ret);
+		return ret;
+	}
+
+	ffa_info("device unbound");
+
+	return 0;
+}
+
+/**
+ * ffa_device_get - create, bind and probe the arm_ffa device
+ *
+ * This boot time function makes sure the arm_ffa device is
+ * created, bound to this driver, probed and ready to use.
+ * Arm FF-A transport is implemented through a single u-boot
+ * device managing the FF-A bus (arm_ffa).
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_device_get(void)
+{
+	int ret;
+	struct udevice *dev = NULL;
+
+	ret = device_bind(dm_root(),
+			  DM_DRIVER_GET(arm_ffa),
+			  FFA_DRV_NAME,
+			  NULL,
+			  ofnode_null(),
+			  &dev);
+	if (ret)
+		return ret;
+
+	/* The FF-A bus discovery succeeds when probing is successful */
+	ret = device_probe(dev);
+	if (ret) {
+		ffa_err("arm_ffa device probing failed");
+		ffa_remove_device(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_version - FFA_VERSION handler function
+ *
+ * This is the boot time function that implements FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_version(void)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION),
+			.a1 = FFA_VERSION_1_0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	ffa_errno = (int)res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION((u32)res.a0);
+	minor = GET_FFA_MINOR_VERSION((u32)res.a0);
+
+	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
+		ffa_info("Versions are compatible ");
+
+		ffa_priv_data->fwk_version = (u32)res.a0;
+
+		return 0;
+	}
+
+	ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id - FFA_ID_GET handler function
+ *
+ * This is the boot time function that implements FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			.a1 = 0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		ffa_info("endpoint ID is %u", ffa_priv_data->id);
+
+		return 0;
+	}
+
+	ffa_errno = (int)res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * This boot time function sets the minimum number of pages
+ *  in each of the RX/TX buffers in the private data structure
+ *
+ * Return:
+ *
+ * buf_4k_pages points to the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
+{
+	if (!ffa_priv_data)
+		return -EINVAL;
+
+	switch (prop_field) {
+	case RXTX_4K:
+		ffa_priv_data->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		ffa_priv_data->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		ffa_priv_data->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		ffa_err("RX/TX buffer size not supported");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ *
+ * This is the boot time function that implements FFA_FEATURES FF-A function
+ * to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt((u32)res.a2);
+
+	ffa_errno = (int)res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers - frees the RX/TX buffers
+ *
+ * This is the boot time function used to free the RX/TX buffers
+ *
+ */
+static void ffa_free_rxtx_buffers(void)
+{
+	ffa_info("Freeing RX/TX buffers");
+
+	if (ffa_priv_data->pair.rxbuf) {
+		free((void *)ffa_priv_data->pair.rxbuf);
+		ffa_priv_data->pair.rxbuf = 0;
+	}
+
+	if (ffa_priv_data->pair.txbuf) {
+		free((void *)ffa_priv_data->pair.txbuf);
+		ffa_priv_data->pair.txbuf = 0;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
+ *
+ * This is the boot time function used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(void)
+{
+	u64 bytes;
+
+	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
+		 ffa_priv_data->pair.rxtx_min_pages);
+
+	bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
+
+	/* RX/TX buffers addresses should be PAGE_SIZE aligned */
+
+	ffa_priv_data->pair.rxbuf = (u64)memalign(PAGE_SIZE, bytes);
+	if (!ffa_priv_data->pair.rxbuf) {
+		ffa_err("failure to allocate RX buffer");
+		return -ENOBUFS;
+	}
+
+	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
+
+	ffa_priv_data->pair.txbuf = (u64)memalign(PAGE_SIZE, bytes);
+	if (!ffa_priv_data->pair.txbuf) {
+		free((void *)ffa_priv_data->pair.rxbuf);
+		ffa_priv_data->pair.rxbuf = 0;
+		ffa_err("failure to allocate the TX buffer");
+		return -ENOBUFS;
+	}
+
+	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
+
+	/*
+	 * make sure the buffers are cleared before use
+	 */
+	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
+	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
+ *
+ * This is the boot time function that implements FFA_RXTX_MAP FF-A function
+ * to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers(void)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ret = ffa_alloc_rxtx_buffers();
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 *no need to convert from virtual to physical
+	 */
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = ffa_priv_data->pair.txbuf,
+			.a2 = ffa_priv_data->pair.rxbuf,
+			.a3 = ffa_priv_data->pair.rxtx_min_pages,
+			.a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_info("RX/TX buffers mapped");
+		return 0;
+	}
+
+	ffa_errno = (int)res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers();
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
+ *
+ * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_unmap_rxtx_buffers(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id),
+			.a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers();
+		return 0;
+	}
+
+	ffa_errno = (int)res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
+ *
+ * This is the boot time function that invokes FFA_RX_RELEASE FF-A function
+ * to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			.a1 = 0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = (int)res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical - checks whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * This is a boot time function used by ffa_read_partitions_info to search
+ * for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+int ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+			   const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return (!memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid)));
+}
+
+/**
+ * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
+ *							and saves it in the private structure
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * This is the boot time function that reads the partitions information
+ * returned by the FFA_PARTITION_INFO_GET and saves it in the private
+ * data structure.
+ *
+ * Return:
+ *
+ * The private data structure is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
+{
+	if (!count) {
+		ffa_err("no partition detected");
+		return -ENODATA;
+	}
+
+	ffa_info("Reading partitions data from the RX buffer");
+
+	if (!part_uuid) {
+		/*
+		 * querying information of all partitions
+		 */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			ffa_err("partitions data size exceeds the RX buffer size:");
+			ffa_err("    sizes in bytes: data %llu , RX buffer %llu ",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		ffa_priv_data->partitions.descs = (struct ffa_partition_desc *)
+			devm_kmalloc(ffa_priv_data->dev, data_bytes, __GFP_ZERO);
+		if (!ffa_priv_data->partitions.descs) {
+			ffa_err("cannot  allocate partitions data buffer");
+			return -ENOMEM;
+		}
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			ffa_priv_data->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			ffa_info("Partition ID %x : info cached",
+				 ffa_priv_data->partitions.descs[desc_idx].info.id);
+		}
+
+		ffa_priv_data->partitions.count = count;
+
+		ffa_info("%d partition(s) found and cached", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
+
+		/*
+		 * search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/*
+			 * search the current ID in the cached partitions
+			 */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < ffa_priv_data->partitions.count;
+			     cached_desc_idx++) {
+				/*
+				 * save the UUID
+				 */
+				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
+ *
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * This is the boot time function that executes the FFA_PARTITION_INFO_GET
+ * to query the partitions data. Then, it calls ffa_read_partitions_info
+ * to save the data in the private data structure.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			.a5 = 0,
+			.a6 = 0,
+			.a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
+			if (ret) {
+				ffa_err("failed to read partition(s) data , error (%d)", ret);
+				ffa_release_rx_buffer();
+				return -EINVAL;
+			}
+		}
+
+		/*
+		 * return the SP count (when querying using a UUID)
+		 */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer();
+
+		return ret;
+	}
+
+	ffa_errno = (int)res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
+ *
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@uuid_str: pointer to the UUID string
+ *	@parts_size: pointer to the variable that contains the number of partitions
+ *			 The variable will be set by the driver
+ *	@buffer: NULL
+ *
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@uuid_str: pointer to the UUID string
+ *	@parts_size: pointer to the size of the SPs information buffer in bytes
+ *	@buffer: pointer to SPs information buffer
+ *		(allocated by the client).
+ *		The buffer will be filled by the driver
+ *
+ * This is the boot time function that queries the secure partition data from
+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * When invoked through a client request, ffa_get_partitions_info should be
+ * called twice. First call is to get from the driver the number of secure
+ * partitions (SPs) associated to a particular UUID.
+ * Then, the caller (client) allocates the buffer to host the SPs data and
+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
+ * buffer.
+ *
+ * To achieve the mechanism described above, ffa_get_partitions_info uses the
+ * following functions:
+ *		ffa_read_partitions_info
+ *		ffa_query_partitions_info
+ *
+ * Return:
+ *
+ * @parts_size: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer size, the buffer will be
+ * filled by the driver.
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+static int ffa_get_partitions_info(const char *uuid_str,
+				   u32 *parts_size, struct ffa_partition_info *buffer)
+{
+	/*
+	 * fill_data:
+	 * 0: return the SP count
+	 * 1: fill SP data and return it to the caller
+	 * -1: undefined mode
+	 */
+	int fill_data = -1;
+	u32 desc_idx, client_desc_idx;
+	struct ffa_partition_uuid part_uuid = {0};
+	u32 client_desc_max_cnt;
+	u32 parts_found = 0;
+
+	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
+		ffa_err("no partition installed");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		ffa_err("no UUID provided");
+		return -EINVAL;
+	}
+
+	if (!parts_size) {
+		ffa_err("no size/count provided");
+		return -EINVAL;
+	}
+
+	if (be_uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		ffa_err("invalid UUID");
+		return -EINVAL;
+	}
+
+	if (!buffer) {
+		/* Mode 1: getting the number of secure partitions */
+
+		fill_data = 0;
+
+		ffa_info("Preparing for checking partitions count");
+
+	} else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
+		   !(*parts_size % sizeof(struct ffa_partition_info))) {
+		/* Mode 2: retrieving the partitions information */
+
+		fill_data = 1;
+
+		client_desc_idx = 0;
+
+		/*
+		 * number of empty descriptors preallocated by the caller
+		 */
+		client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
+
+		ffa_info("Preparing for filling partitions info");
+
+	} else {
+		ffa_err("invalid function arguments provided");
+		return -EINVAL;
+	}
+
+	ffa_info("Searching partitions using the provided UUID");
+
+	/*
+	 * search in the cached partitions
+	 */
+	for (desc_idx = 0;
+	     desc_idx < ffa_priv_data->partitions.count;
+	     desc_idx++) {
+		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
+					   &part_uuid)) {
+			ffa_info("Partition ID %x matches the provided UUID",
+				 ffa_priv_data->partitions.descs[desc_idx].info.id);
+
+			parts_found++;
+
+			if (fill_data) {
+				/*
+				 * trying to fill the partition info in the input buffer
+				 */
+
+				if (client_desc_idx < client_desc_max_cnt) {
+					buffer[client_desc_idx++] =
+						ffa_priv_data->partitions.descs[desc_idx].info;
+					continue;
+				}
+
+				ffa_err("failed to fill the current descriptor client buffer full");
+				return -ENOBUFS;
+			}
+		}
+	}
+
+	if (!parts_found) {
+		int ret;
+
+		ffa_info("No partition found. Querying framework ...");
+
+		ret = ffa_query_partitions_info(&part_uuid, &parts_found);
+
+		if (ret == 0) {
+			if (!fill_data) {
+				*parts_size = parts_found;
+
+				ffa_info("Number of partition(s) found matching the UUID: %d",
+					 parts_found);
+			} else {
+				/*
+				 * If SPs data detected, they are already in the private data
+				 * structure, retry searching SP data again to return them
+				 *  to the caller
+				 */
+				if (parts_found)
+					ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
+				else
+					ret = -ENODATA;
+			}
+		}
+
+		return ret;
+	}
+
+	/* partition(s) found */
+	if (!fill_data)
+		*parts_size = parts_found;
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info - Queries and saves all secure partitions data
+ *
+ * This is a boot time function that invokes FFA_PARTITION_INFO_GET FF-A
+ * function to query from secure world all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in the
+ * resident private data structure and we keep the UUID field empty
+ * (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * This function is called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(void)
+{
+	return ffa_query_partitions_info(NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ *
+ * This is the runtime function that implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int __ffa_runtime ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
+		return -EINVAL;
+
+	/* No partition installed */
+	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
+		return -ENODEV;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ),
+			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP)) {
+		/*
+		 * Message sent with response
+		 * extract the return data
+		 */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = (int)res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * __arm_ffa_fn_smc - 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 low level SMC assembly function
+ *
+ * Return: void
+ */
+void __ffa_runtime __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * ffa_set_smc_conduit - Set the SMC conduit
+ *
+ * This boot time function selects the SMC conduit by setting the driver invoke function
+ * to SMC assembly function
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_smc_conduit(void)
+{
+	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
+
+	if (!ffa_priv_data->invoke_ffa_fn) {
+		ffa_err("failure to set the invoke function");
+		return -EINVAL;
+	}
+
+	ffa_info("Conduit is SMC");
+
+	return 0;
+}
+
+/**
+ * ffa_set_bus_ops - Set the bus driver operations
+ *
+ * Setting the driver callbacks.
+ *
+ */
+static void ffa_set_bus_ops(void)
+{
+	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
+	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
+	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
+}
+
+/**
+ * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
+ * @dev:	the arm_ffa device
+ *
+ * This boot time function creates the main data structure embedding all the driver data.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_prvdata(struct udevice *dev)
+{
+	if (!dev) {
+		ffa_err("no udevice found");
+		return -ENODEV;
+	}
+
+	/* The device is registered with the DM. Let's create the driver main data structure*/
+
+	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
+	if (!ffa_priv_data) {
+		ffa_err("can not allocate the driver main data structure");
+		return -ENOMEM;
+	}
+
+	ffa_priv_data->dev = dev;
+
+	return 0;
+}
+
+/**
+ * ffa_probe - The driver probe function
+ * @dev:	the arm_ffa device
+ *
+ * Probing is done at boot time and triggered by the uclass device discovery.
+ * At probe level the following actions are done:
+ *	- setting the conduit
+ *	- querying the FF-A framework version
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in the resident private data structure.
+ *
+ * The probe will fail if either FF-A framework is not detected or the
+ * FF-A requests are not behaving correctly. This ensures that the
+ * driver is not installed and its operations are not exported to the clients.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = ffa_alloc_prvdata(dev);
+	if (ret != 0)
+		return ret;
+
+	ffa_set_bus_ops();
+
+	ret = ffa_set_smc_conduit();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_version();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_endpoint_id();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_cache_partitions_info();
+	if (ret != 0) {
+		ffa_free_rxtx_buffers();
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_remove - The driver remove function
+ * @dev:	the arm_ffa device
+ * When the device is about to be removed ,  unmap the RX/TX buffers and free the memory
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_remove(struct udevice *dev)
+{
+	ffa_info("removing the device");
+
+	ffa_unmap_rxtx_buffers();
+
+	if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
+		ffa_free_rxtx_buffers();
+
+	return 0;
+}
+
+/**
+ * ffa_unbind - The driver unbind function
+ * @dev:	the arm_ffa device
+ * After the device is removed and memory freed the device is unbound
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_unbind(struct udevice *dev)
+{
+	ffa_info("unbinding the device , private data already released");
+
+	ffa_priv_data = NULL;
+
+	return 0;
+}
+
+/**
+ * ffa_bus_ops_get - bus driver operations getter
+ *
+ * Return:
+ * This runtime function returns a pointer to the driver operations structure
+ */
+const struct ffa_bus_ops * __ffa_runtime ffa_bus_ops_get(void)
+{
+	return &ffa_priv_data->ffa_ops;
+}
+
+/**
+ * ffa_bus_prvdata_get - bus driver private data getter
+ *
+ * Return:
+ * This boot time function returns a pointer to the main private data structure
+ */
+struct ffa_prvdata **ffa_bus_prvdata_get(void)
+{
+	return &ffa_priv_data;
+}
+
+/**
+ * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
+ *
+ * This boot time function makes sure the FF-A bus is discoverable.
+ * Then, the arm_ffa device is probed and 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.
+ * All FF-A clients should use the arm_ffa device to use the FF-A transport.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_bus_discover(void)
+{
+	int ret = 0;
+
+	if (!ffa_priv_data)
+		ret = ffa_device_get();
+
+	return ret;
+}
+
+/**
+ * Declaring the arm_ffa driver under UCLASS_FFA
+ */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.probe		= ffa_probe,
+	.remove		= ffa_remove,
+	.unbind		= ffa_unbind,
+};
diff --git a/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c b/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
new file mode 100644
index 0000000000..c76cf2147b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include "arm_ffa_prv.h"
+
+/**
+ * ffa_copy_runtime_data - copy the private data structure  to the runtime area
+ *
+ * This boot time function copies the arm_ffa driver data structures including
+ *  partitions data to the EFI runtime data section.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+efi_status_t ffa_copy_runtime_data(void)
+{
+	efi_status_t efi_ret;
+	efi_uintn_t prvdata_pages;
+	efi_uintn_t descs_pages;
+	struct ffa_prvdata **prvdata = NULL; /* Pointer to the current structure */
+	struct ffa_prvdata *runtime_prvdata = NULL; /* Pointer to the structure runtime copy */
+	u64 runtime_descs = 0;
+
+	prvdata = ffa_bus_prvdata_get();
+
+	printf("INFO: EFI: FFA: prv data area at 0x%llx\n", (u64)prvdata);
+
+	/* allocate private data runtime area */
+
+	prvdata_pages = efi_size_in_pages(sizeof(struct ffa_prvdata));
+	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				     EFI_RUNTIME_SERVICES_DATA,
+				     prvdata_pages,
+				     (u64 *)&runtime_prvdata);
+
+	if (efi_ret != EFI_SUCCESS) {
+		printf("ERROR: EFI: FFA: allocating runtime data (err: 0x%lx, addr 0x%llx)\n",
+		       efi_ret, (u64)runtime_prvdata);
+
+		return efi_ret;
+	}
+
+	printf("INFO: EFI: FFA: runtime data area at 0x%llx\n", (u64)runtime_prvdata);
+
+	if (!runtime_prvdata)
+		return EFI_INVALID_PARAMETER;
+
+	/* allocate the partition data runtime area */
+
+	descs_pages = efi_size_in_pages((*prvdata)->partitions.count *
+					sizeof(struct ffa_partition_desc));
+	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				     EFI_RUNTIME_SERVICES_DATA,
+				     descs_pages,
+				     &runtime_descs);
+
+	if (efi_ret != EFI_SUCCESS) {
+		printf("ERROR: EFI: FFA: allocating runtime SPs data (err: 0x%lx, addr 0x%llx)\n",
+		       efi_ret, runtime_descs);
+
+		efi_free_pages((u64)runtime_prvdata, prvdata_pages);
+
+		return efi_ret;
+	}
+
+	printf("INFO: EFI: FFA: SPs runtime area at 0x%llx\n", (u64)runtime_descs);
+
+	if (!runtime_descs)
+		return EFI_INVALID_PARAMETER;
+
+	*runtime_prvdata = **prvdata;
+
+	runtime_prvdata->dev = NULL;
+	runtime_prvdata->ffa_ops.partition_info_get = NULL;
+	runtime_prvdata->ffa_ops.rxtx_unmap = NULL;
+	runtime_prvdata->partitions.descs = (struct ffa_partition_desc *)runtime_descs;
+	runtime_prvdata->pair.rxbuf = 0;
+	runtime_prvdata->pair.txbuf = 0;
+
+	/*
+	 * Update the private data structure pointer in the driver
+	 * no need to free the old structure. devm takes care of that
+	 */
+	*prvdata = runtime_prvdata;
+
+	printf("INFO: EFI: FFA: runtime prv data now at 0x%llx , SPs count %d\n",
+	       (u64)*prvdata, (*prvdata)->partitions.count);
+
+	return 0;
+}
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..f17b100497
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * Macros for displaying logs
+ */
+
+#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
+#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct  __packed ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct __packed ffa_send_direct_data {
+	unsigned long data0; /* w3/x3 */
+	unsigned long data1; /* w4/x4 */
+	unsigned long data2; /* w5/x5 */
+	unsigned long data3; /* w6/x6 */
+	unsigned long data4; /* w7/x7 */
+};
+
+#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
+
+#include <efi_loader.h>
+
+/*
+ *  __ffa_runtime - controls whether functions are
+ * available after calling the EFI ExitBootServices service.
+ * Functions tagged with these keywords are resident (available at boot time and
+ * at runtime)
+ */
+
+#define __ffa_runtime_data __efi_runtime_data
+#define __ffa_runtime __efi_runtime
+
+#else
+
+/*
+ *  The FF-A driver is independent from EFI
+ */
+
+#define __ffa_runtime_data
+#define __ffa_runtime
+
+#endif
+
+/**
+ * struct ffa_bus_ops - The driver operations structure
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(const char *uuid_str,
+				  u32 *parts_size, struct ffa_partition_info *buffer);
+	int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg);
+	int (*rxtx_unmap)(void);
+};
+
+/**
+ * The device driver and the Uclass driver public functions
+ */
+
+/**
+ * ffa_bus_ops_get - driver operations getter
+ */
+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
+ */
+int ffa_bus_discover(void);
+
+#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
+
+/**
+ * ffa_copy_runtime_data - copy the private data structure and the SPs data to the runtime area
+ */
+efi_status_t ffa_copy_runtime_data(void);
+
+#endif
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index a432e43871..5dd698b7a9 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,9 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -55,6 +58,7 @@ enum uclass_id {
 	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
 	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 6f7333638a..af0b0f3db1 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -3,6 +3,9 @@
  * EFI application boot time services
  *
  * Copyright (c) 2016 Alexander Graf
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -23,6 +26,10 @@
 #include <asm/setjmp.h>
 #include <linux/libfdt_env.h>
 
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+#include <arm_ffa.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Task priority level */
@@ -2178,6 +2185,14 @@ 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)
+		/* 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");
+		else
+			debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
+#endif
+
 	/* Patch out unsupported runtime function */
 	efi_runtime_detach();
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v4 05/10] arm_ffa: introduce armffa command
  2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                   ` (3 preceding siblings ...)
  2022-09-26 10:17                                 ` [PATCH v4 04/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
@ 2022-09-26 10:17                                 ` Abdellatif El Khlifi
  2022-09-26 10:17                                 ` [PATCH v4 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
                                                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 10:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, ilias.apalodimas, jens.wiklander, trini, sjg,
	vishnu.banavath, xueliang.zhong, achin.gupta, nd

Provide armffa command showcasing the use of the FF-A driver

The armffa command allows to query secure partitions data from
the secure world and exchanging messages with the partitions.

Changelog:
===============

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

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>
---
 MAINTAINERS                      |   1 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   2 +
 cmd/armffa.c                     | 242 +++++++++++++++++++++++++++++++
 drivers/firmware/arm-ffa/Kconfig |   1 +
 5 files changed, 256 insertions(+)
 create mode 100644 cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 02b84d5074..fd3b2c4263 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -251,6 +251,7 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+F:	cmd/armffa.c
 F:	doc/README.ffa.drv
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 0e0be94f41..013d4c3da7 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -912,6 +912,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the Arm FF-A driver
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index 6e87522b62..979c6d59df 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,8 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
 obj-$(CONFIG_CMD_AES) += aes.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..9b56e8a830
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <arm_ffa.h>
+#include <asm/io.h>
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+
+/**
+ * do_ffa_get_singular_partition_info - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver partition_info_get operation
+ * to retrieve the data.
+ * The input UUID string is expected to be in big endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_get_singular_partition_info(struct cmd_tbl *cmdtp, int flag, int argc,
+					      char *const argv[])
+{
+	u32 count = 0, size = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	/* Mode 1: getting the number of secure partitions */
+	ret = ffa_bus_ops_get()->partition_info_get(argv[0], &count, NULL);
+	if (ret != 0) {
+		ffa_err("Failure in querying partitions count (error code: %d)", ret);
+		return ret;
+	}
+
+	if (!count) {
+		ffa_info("No secure partition found");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with ffa_partition_info structs
+	 */
+
+	ffa_info("Pre-allocating %d partition(s) info structures", count);
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	size = count * sizeof(struct ffa_partition_info);
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+
+	ret = ffa_bus_ops_get()->partition_info_get(argv[0], &size, parts_info);
+	if (ret != 0) {
+		ffa_err("Failure in querying partition(s) info (error code: %d)", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * SPs found , show the partition information
+	 */
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		ffa_info("Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x",
+			 parts_info[info_idx].id,
+			 parts_info[info_idx].exec_ctxt,
+			 parts_info[info_idx].properties);
+	}
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * do_ffa_msg_send_direct_req - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function sends data to the secure partition which the ID is provided
+ * as an argument. The function uses the arm_ffa driver sync_send_receive operation
+ * to send data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int  do_ffa_msg_send_direct_req(struct cmd_tbl *cmdtp, int flag, int argc,
+				char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	errno = 0;
+	part_id = strtoul(argv[0], NULL, 16);
+
+	if (errno) {
+		ffa_err("Invalid partition ID");
+		return -EINVAL;
+	}
+
+	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
+	if (ret == 0) {
+		u8 cnt;
+
+		ffa_info("SP response:\n[LSB]");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			ffa_info("0x%llx", ((u64 *)&msg)[cnt]);
+	} else {
+		ffa_err("Sending direct request error (%d)", ret);
+	}
+
+	return ret;
+}
+
+/**
+ *do_ffa_dev_list - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the devices belonging to the UCLASS_FFA
+ * class. Currently, one device is expected to show up: the arm_ffa device
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_dev_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev = NULL;
+	int i, ret;
+
+	ffa_info("arm_ffa uclass entries:");
+
+	for (i = 0, ret = uclass_first_device(UCLASS_FFA, &dev);
+	     dev;
+	     ret = uclass_next_device(&dev), i++) {
+		if (ret)
+			break;
+
+		ffa_info("entry %d - instance %08x, ops %08x, plat %08x",
+			 i,
+			 (u32)map_to_sysmem(dev),
+			 (u32)map_to_sysmem(dev->driver->ops),
+			 (u32)map_to_sysmem(dev_get_plat(dev)));
+	}
+
+	return cmd_process_error(cmdtp, ret);
+}
+
+static struct cmd_tbl armffa_commands[] = {
+	U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_get_singular_partition_info, "", ""),
+	U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_msg_send_direct_req, "", ""),
+	U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_dev_list, "", ""),
+};
+
+/**
+ * do_armffa - the armffa command main function
+ * @cmdtp:	Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function identifies which armffa subcommand to run.
+ * Then, it makes sure the arm_ffa device is probed and
+ * ready for use.
+ * Then, it runs the subcommand.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct cmd_tbl *armffa_cmd;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
+
+	argc -= 2;
+	argv += 2;
+
+	if (!armffa_cmd || argc > armffa_cmd->maxargs)
+		return CMD_RET_USAGE;
+
+	ret = ffa_bus_discover();
+	if (ret != 0)
+		return cmd_process_error(cmdtp, ret);
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
+
+	return cmd_process_error(armffa_cmd, ret);
+}
+
+U_BOOT_CMD(armffa, 4, 1, do_armffa,
+	   "Arm FF-A operations test command",
+	   "getpart <partition UUID>\n"
+	   "	 - lists the partition(s) info\n"
+	   "ping <partition ID>\n"
+	   "	 - sends a data pattern to the specified partition\n"
+	   "devlist\n"
+	   "	 - displays the arm_ffa device info\n");
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index aceb61cf49..40b467b0a5 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -4,6 +4,7 @@ config ARM_FFA_TRANSPORT
 	bool "Enable Arm Firmware Framework for Armv8-A driver"
 	depends on DM && ARM64
 	select ARM_SMCCC
+	select CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v4 06/10] arm_ffa: introduce the FF-A Sandbox driver
  2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                   ` (4 preceding siblings ...)
  2022-09-26 10:17                                 ` [PATCH v4 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2022-09-26 10:17                                 ` Abdellatif El Khlifi
  2022-09-26 10:17                                 ` [PATCH v4 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 10:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, ilias.apalodimas, jens.wiklander, trini, sjg,
	vishnu.banavath, xueliang.zhong, achin.gupta, nd

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>
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>

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 fd3b2c4263..6f01002e34 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -255,6 +255,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 8c99faddfd..7f1eae65df 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -776,7 +776,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 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 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 af0b0f3db1..d404343a7d 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())
 			debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n");
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v4 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                   ` (5 preceding siblings ...)
  2022-09-26 10:17                                 ` [PATCH v4 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
@ 2022-09-26 10:17                                 ` Abdellatif El Khlifi
  2022-09-26 10:17                                 ` [PATCH v4 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 10:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, ilias.apalodimas, jens.wiklander, trini, sjg,
	vishnu.banavath, xueliang.zhong, achin.gupta, nd

Add functional test cases for the FF-A core driver

These tests rely on the FF-A Sandbox driver which helps in
 inspecting the FF-A core driver.

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>

Changelog:
===============

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

v1: introduce sandbox tests
---
 MAINTAINERS      |   1 +
 test/dm/Makefile |   2 +
 test/dm/ffa.c    | 394 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 397 insertions(+)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 6f01002e34..8c0dfff5f8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -256,6 +256,7 @@ F:	doc/README.ffa.drv
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/sandbox_arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 7543df8823..e5a791768e 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# (C) Copyright 2022 ARM Limited
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -81,6 +82,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_SANDBOX_FFA) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..052d5fc3f4
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <dm.h>
+#include <dm/test.h>
+#include "../../drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h"
+#include <sandbox_arm_ffa.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Macros */
+
+#define LOG_MSG_SZ (100)
+#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
+
+/* Functional tests for the UCLASS_FFA */
+
+static int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
+{
+	char cmd[LOG_CMD_SZ] = {0};
+
+	console_record_reset();
+
+	snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
+	run_command(cmd, 0);
+
+	ut_assert_console_end();
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_fwk_version(struct ffa_prvdata *prvdata, struct sandbox_ffa_prvdata *sdx_prvdata,
+			     struct unit_test_state *uts)
+{
+	if (prvdata->fwk_version != sdx_prvdata->fwk_version) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: framework version: core = 0x%x , sandbox  = 0x%x", __func__,
+			 prvdata->fwk_version,
+			sdx_prvdata->fwk_version);
+
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_endpoint_id(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (prvdata->id) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: endpoint id: core = 0x%x", __func__, prvdata->id);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_core_dev(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->dev) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: core device NULL", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_sandbox_dev(struct sandbox_ffa_prvdata *sdx_prvdata, struct unit_test_state *uts)
+{
+	if (!sdx_prvdata->dev) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: sandbox device NULL", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_rxtxbuf(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->pair.rxbuf && prvdata->pair.txbuf) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = 0x%llx txbuf = 0x%llx", __func__,
+			 prvdata->pair.rxbuf,
+			 prvdata->pair.txbuf);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_features(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	if (prvdata->pair.rxtx_min_pages != RXTX_4K &&
+	    prvdata->pair.rxtx_min_pages != RXTX_16K &&
+	    prvdata->pair.rxtx_min_pages != RXTX_64K) {
+		snprintf(msg,
+			 LOG_MSG_SZ,
+			 "[%s]: Error: FFA_RXTX_MAP features = 0x%lx",
+			 __func__,
+			 prvdata->pair.rxtx_min_pages);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+	{
+		if (rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	case FFA_RXTX_UNMAP:
+	{
+		if (!rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	default:
+		return CMD_RET_FAILURE;
+	}
+
+	snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__,
+		 (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP"));
+	dm_test_ffa_log(uts, msg);
+
+	return CMD_RET_FAILURE;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	if (rxbuf_owned) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg = {0};
+	u8 cnt;
+
+	ut_assertok(ffa_bus_ops_get()->sync_send_receive(part_id, &msg));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_assertok(((u64 *)&msg)[cnt] != 0xffffffffffffffff);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct sandbox_ffa_prvdata *sdx_prvdata,
+				     struct unit_test_state *uts)
+{
+	u32 count = 0, size = 0;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx, exp_info_idx;
+	int ret;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &count, NULL);
+	/* make sure partitions are detected */
+	ut_assertok(ret != 0);
+	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	ut_assertok(!parts_info);
+
+	size = count * sizeof(struct ffa_partition_info);
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &size, parts_info);
+	if (ret != 0) {
+		free(parts_info);
+		ut_assertok(ret != 0);
+	}
+
+	/*
+	 * SPs found , verify the partitions information
+	 */
+
+	ret = CMD_RET_FAILURE;
+
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		for (exp_info_idx = 0;
+		     exp_info_idx < sdx_prvdata->partitions.count;
+		     exp_info_idx++) {
+			if (parts_info[info_idx].id ==
+			   sdx_prvdata->partitions.descs[exp_info_idx].info.id) {
+				ret = memcmp(&parts_info[info_idx],
+					     &sdx_prvdata->partitions.descs[exp_info_idx]
+					     .info,
+					     sizeof(struct ffa_partition_info));
+				if (ret)
+					free(parts_info);
+				ut_assertok(ret != 0);
+				/* send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
+			}
+			ret = CMD_RET_SUCCESS;
+		}
+	}
+
+	free(parts_info);
+
+	/* Verify  expected partitions found in the emulated secure world*/
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+	struct ffa_sandbox_data func_data = {0};
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	int ret;
+
+	/*  test probing FF-A devices */
+	ut_assertok(ffa_bus_discover());
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+
+	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
+
+	/* make sure private data pointers are retrieved */
+	ut_assertok(prvdata == 0);
+	ut_assertok(sdx_prvdata == 0);
+
+	/* make sure dev devices created */
+	ut_assertok(check_core_dev(prvdata, uts));
+	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
+
+	/* test FFA_VERSION */
+	ut_assertok(check_fwk_version(prvdata, sdx_prvdata, uts));
+
+	/* test FFA_ID_GET */
+	ut_assertok(check_endpoint_id(prvdata, uts));
+
+	/* test FFA_FEATURES */
+	ut_assertok(check_features(prvdata, uts));
+
+	/*  test core RX/TX buffers */
+	ut_assertok(check_rxtxbuf(prvdata, uts));
+
+	/* test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_MAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc1_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc2_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* test FFA_RXTX_UNMAP */
+	ut_assertok(ffa_bus_ops_get()->rxtx_unmap());
+
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_UNMAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+	struct ffa_sandbox_data func_data = {0};
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	u32 count = 0;
+	u16 part_id = 0;
+
+	/*  test probing FF-A devices */
+	ut_assertok(ffa_bus_discover());
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+
+	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
+
+	/* make sure private data pointers are retrieved */
+	ut_assertok(prvdata == 0);
+	ut_assertok(sdx_prvdata == 0);
+
+	/* make sure dev devices created */
+	ut_assertok(check_core_dev(prvdata, uts));
+	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
+
+	/* query partitions count using  invalid arguments  */
+	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, NULL, NULL);
+	ut_assertok(ret != -EINVAL);
+
+	/* query partitions count using an invalid UUID  string */
+	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid_str, &count, NULL);
+	ut_assertok(ret != -EINVAL);
+
+	/* query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, &count, NULL);
+	ut_assertok(count != 0);
+
+	/* query partitions count using a valid UUID  */
+	count = 0;
+	ret = ffa_bus_ops_get()->partition_info_get(valid_svc_uuid, &count, NULL);
+	/* make sure partitions are detected */
+	ut_assertok(ret != 0);
+	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
+
+	/* send data to an invalid partition */
+	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
+	ut_assertok(ret != -EINVAL);
+
+	/* send data to a valid partition */
+	part_id = prvdata->partitions.descs[0].info.id;
+	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
+	ut_assertok(ret != 0);
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v4 08/10] arm_ffa: introduce armffa command Sandbox test
  2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                   ` (6 preceding siblings ...)
  2022-09-26 10:17                                 ` [PATCH v4 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2022-09-26 10:17                                 ` Abdellatif El Khlifi
  2022-09-26 10:17                                 ` [PATCH v4 09/10] arm_ffa: introduce FF-A MM communication Abdellatif El Khlifi
                                                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 10:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, ilias.apalodimas, jens.wiklander, trini, sjg,
	vishnu.banavath, xueliang.zhong, achin.gupta, nd

Add Sandbox test for the armffa command

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>

Changelog:
===============

v4: drop use of helper APIs

v1: introduce armffa command sandbox test
---
 MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 40 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 43 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 8c0dfff5f8..8ed94da4c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -256,6 +256,7 @@ F:	doc/README.ffa.drv
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/sandbox_arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index c331757425..19e9d0a995 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# (C) Copyright 2022 ARM Limited
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -13,3 +14,4 @@ obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
 obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PWM) += pwm.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_SANDBOX_FFA) += armffa.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..531f82066e
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <sandbox_arm_ffa.h>
+#include <string.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define PING_CMD_SIZE 19
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	char ping_cmd[PING_CMD_SIZE] = {0};
+
+	ut_assertok(ffa_bus_discover());
+
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	snprintf(ping_cmd, PING_CMD_SIZE, "armffa ping 0x%x", SANDBOX_SP1_ID);
+
+	/* armffa ping <ID> */
+	ut_assertok(run_command(ping_cmd, 0));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v4 09/10] arm_ffa: introduce FF-A MM communication
  2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                   ` (7 preceding siblings ...)
  2022-09-26 10:17                                 ` [PATCH v4 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2022-09-26 10:17                                 ` Abdellatif El Khlifi
  2022-09-26 10:17                                 ` [PATCH v4 10/10] arm_ffa: corstone1000: enable EFI " Abdellatif El Khlifi
  2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 10:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, ilias.apalodimas, jens.wiklander, trini, sjg,
	vishnu.banavath, xueliang.zhong, achin.gupta, nd,
	Gowtham Suresh Kumar

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

FF-A driver private data is copied to EFI runtime section at
ExitBootServices(). This garantees secure world partitions data are
available at EFI runtime level.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>

Changelog:
===============

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication
---
 arch/arm/cpu/armv8/cache.S        |  19 +++
 arch/arm/cpu/armv8/cache_v8.c     |   6 +-
 include/mm_communication.h        |   9 +-
 lib/efi_loader/Kconfig            |  14 +-
 lib/efi_loader/efi_boottime.c     |   7 +
 lib/efi_loader/efi_variable_tee.c | 263 +++++++++++++++++++++++++++++-
 6 files changed, 309 insertions(+), 9 deletions(-)

diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S
index d1cee23437..91b7c73c17 100644
--- a/arch/arm/cpu/armv8/cache.S
+++ b/arch/arm/cpu/armv8/cache.S
@@ -3,6 +3,9 @@
  * (C) Copyright 2013
  * David Feng <fenghua@phytium.com.cn>
  *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ *
  * This file is based on sample code from ARMv8 ARM.
  */
 
@@ -21,7 +24,11 @@
  * x1: 0 clean & invalidate, 1 invalidate only
  * x2~x9: clobbered
  */
+#ifdef CONFIG_EFI_LOADER
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_dcache_level, "ax"
+#endif
 ENTRY(__asm_dcache_level)
 	lsl	x12, x0, #1
 	msr	csselr_el1, x12		/* select cache level */
@@ -65,7 +72,11 @@ ENDPROC(__asm_dcache_level)
  *
  * flush or invalidate all data cache by SET/WAY.
  */
+#ifdef CONFIG_EFI_LOADER
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_dcache_all, "ax"
+#endif
 ENTRY(__asm_dcache_all)
 	mov	x1, x0
 	dsb	sy
@@ -109,7 +120,11 @@ ENTRY(__asm_flush_dcache_all)
 ENDPROC(__asm_flush_dcache_all)
 .popsection
 
+#ifdef CONFIG_EFI_LOADER
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_invalidate_dcache_all, "ax"
+#endif
 ENTRY(__asm_invalidate_dcache_all)
 	mov	x0, #0x1
 	b	__asm_dcache_all
@@ -182,7 +197,11 @@ ENTRY(__asm_invalidate_icache_all)
 ENDPROC(__asm_invalidate_icache_all)
 .popsection
 
+#ifdef CONFIG_EFI_LOADER
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_invalidate_l3_dcache, "ax"
+#endif
 WEAK(__asm_invalidate_l3_dcache)
 	mov	x0, #0			/* return status as success */
 	ret
diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index e4736e5643..45f57372c2 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -5,10 +5,14 @@
  *
  * (C) Copyright 2016
  * Alexander Graf <agraf@suse.de>
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
 #include <cpu_func.h>
+#include <efi_loader.h>
 #include <hang.h>
 #include <log.h>
 #include <asm/cache.h>
@@ -445,7 +449,7 @@ __weak void mmu_setup(void)
 /*
  * Performs a invalidation of the entire data cache at all levels
  */
-void invalidate_dcache_all(void)
+void __efi_runtime invalidate_dcache_all(void)
 {
 	__asm_invalidate_dcache_all();
 	__asm_invalidate_l3_dcache();
diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..fe9104c56d 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,8 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +15,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
@@ -43,7 +48,7 @@
  * To avoid confusion in interpreting frames, the communication buffer should
  * always begin with efi_mm_communicate_header.
  */
-struct __packed efi_mm_communicate_header {
+struct efi_mm_communicate_header {
 	efi_guid_t header_guid;
 	size_t     message_len;
 	u8         data[];
@@ -145,7 +150,7 @@ struct smm_variable_communicate_header {
  * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
  *
  */
-struct smm_variable_access {
+struct __packed smm_variable_access {
 	efi_guid_t  guid;
 	efi_uintn_t data_size;
 	efi_uintn_t name_size;
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index b8fb2701a7..d292f57244 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -61,13 +61,23 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	depends on OPTEE || ARM_FFA_TRANSPORT
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index d404343a7d..8a397ea21b 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -2193,6 +2193,13 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 			debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
 #endif
 
+#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE) && !CONFIG_IS_ENABLED(SANDBOX_FFA)
+		if (ffa_copy_runtime_data())
+			printf("ERROR: EFI: FFA: copying runtime data\n");
+		else
+			printf("INFO: EFI: FFA: runtime data copied\n");
+#endif
+
 	/* Patch out unsupported runtime function */
 	efi_runtime_detach();
 
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..d6f24f85bd 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,6 +4,8 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright (C) 2022 ARM Limited
+ *  Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -15,6 +17,36 @@
 #include <malloc.h>
 #include <mm_communication.h>
 
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+#include <arm_ffa.h>
+#include <cpu_func.h>
+#include <mapmem.h>
+
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+#warning "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_SIZE 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_OFFSET
+#warning "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_OFFSET 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+#warning "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_ADDR 0
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+
+const char *mm_sp_svc_uuid = MM_SP_UUID;
+
+static __efi_runtime_data u16 mm_sp_id;
+
+#endif
+
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -24,6 +56,7 @@ struct mm_connection {
 	u32 session;
 };
 
+#if (IS_ENABLED(CONFIG_OPTEE))
 /**
  * get_connection() - Retrieve OP-TEE session for a specific UUID.
  *
@@ -143,16 +176,227 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 
 	return ret;
 }
+#endif
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notifies the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int __efi_runtime ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret = -1;
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
+
+	ret = ffa_bus_ops_get()->sync_send_receive(mm_sp_id, &msg);
+	if (ret != 0)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	if (sp_event_ret == MM_SUCCESS)
+		return 0;
+
+	/*
+	 * Failure to notify the MM SP
+	 */
+
+	return -EACCES;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0, size = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &count, NULL);
+	if (ret != 0) {
+		log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
+		return ret;
+	}
+
+	if (!count) {
+		log_info("EFI: No MM partition found\n");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	size = count * sizeof(struct ffa_partition_info);
+
+	/*
+	 * ask the driver to fill the
+	 * buffer with the SPs info
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &size, parts_info);
+	if (ret != 0) {
+		log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * MM SPs found , use the first one
+	 */
+
+	mm_sp_id = parts_info[0].id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t __efi_runtime ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
+		log_err("EFI: Failure to discover MM partition ID at boot time\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	efi_memcpy_runtime(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+	#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+	#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+	if (ffa_ret)
+		unmap_sysmem(virt_shared_buf);
+
+	switch (ffa_ret) {
+	case 0:
+	{
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			unmap_sysmem(virt_shared_buf);
+			return EFI_OUT_OF_RESOURCES;
+		}
+
+		efi_memcpy_runtime(comm_buf, virt_shared_buf, rx_data_size);
+		unmap_sysmem(virt_shared_buf);
+
+		return EFI_SUCCESS;
+	}
+	case -EINVAL:
+		return EFI_DEVICE_ERROR;
+	case -EPERM:
+		return EFI_INVALID_PARAMETER;
+	case -EACCES:
+		return EFI_ACCESS_DENIED;
+	case -EBUSY:
+		return EFI_OUT_OF_RESOURCES;
+	default:
+		return EFI_ACCESS_DENIED;
+	}
+}
+#endif
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, StandAlonneMM and smm-gateway are supported.
+ *
  * Return:		status code
  */
-static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
+static efi_status_t __efi_runtime mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 {
 	efi_status_t ret;
 	struct efi_mm_communicate_header *mm_hdr;
@@ -162,7 +406,11 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
+	#if (IS_ENABLED(CONFIG_OPTEE))
 	ret = optee_mm_communicate(comm_buf, dsize);
+	#elif (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+	ret = ffa_mm_communicate(comm_buf, dsize);
+	#endif
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -258,6 +506,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
 		goto out;
 	}
 	*size = var_payload->size;
+
+	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
+			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
+				MM_VARIABLE_COMMUNICATE_SIZE;
+	#endif
+
 	/*
 	 * There seems to be a bug in EDK2 miscalculating the boundaries and
 	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
@@ -697,7 +952,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v4 10/10] arm_ffa: corstone1000: enable EFI MM communication
  2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                   ` (8 preceding siblings ...)
  2022-09-26 10:17                                 ` [PATCH v4 09/10] arm_ffa: introduce FF-A MM communication Abdellatif El Khlifi
@ 2022-09-26 10:17                                 ` Abdellatif El Khlifi
  2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 10:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: u-boot, ilias.apalodimas, jens.wiklander, trini, sjg,
	vishnu.banavath, xueliang.zhong, achin.gupta, nd

turn on EFI MM communication

On corstone1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

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>
---
 configs/corstone1000_defconfig | 4 ++++
 include/configs/corstone1000.h | 9 +++++++++
 2 files changed, 13 insertions(+)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index ed2e0fe70a..5028c746c5 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -52,3 +52,7 @@ CONFIG_DM_SERIAL=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760=y
 CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
+# CONFIG_OPTEE is not set
+CONFIG_ARM_FFA_TRANSPORT=y
+CONFIG_ARM_FFA_EFI_RUNTIME_MODE=y
diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
index 8e0230c135..997d0bebaf 100644
--- a/include/configs/corstone1000.h
+++ b/include/configs/corstone1000.h
@@ -14,6 +14,15 @@
 
 #include <linux/sizes.h>
 
+#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
+
+/*
+ * shared buffer physical address used for communication between
+ * u-boot and the MM SP
+ */
+#define FFA_SHARED_MM_BUFFER_ADDR	(0x023F8000)
+#define FFA_SHARED_MM_BUFFER_OFFSET	(0)
+
 #define V2M_BASE		0x80000000
 
 #define CONFIG_PL011_CLOCK	50000000
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v2 1/6] arm_ffa: introduce Arm FF-A low-level driver
  2022-05-13 14:23                       ` Ilias Apalodimas
@ 2022-09-26 10:42                         ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 10:42 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, nd

On Fri, May 13, 2022 at 05:23:19PM +0300, Ilias Apalodimas wrote:
> Hi Abdellatif
> On Fri, Apr 15, 2022 at 01:27:58PM +0100, abdellatif.elkhlifi@arm.com wrote:
> > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > 
> > Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
> > 
> > The Firmware Framework for Arm A-profile processors (FF-A)
> > describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World leveraging TrustZone
> > technology. This driver uses SMC32 calling convention.
> > 
> > In u-boot FF-A design, FF-A is considered as a discoverable bus.
> > The Secure World is considered as one entity to communicate with
> > using the FF-A bus. FF-A communication is handled by one device and
> > one instance (the bus). This FF-A driver takes care of all the
> > interactions between Normal world and Secure World.
> > 
> > The driver provides helper FF-A interfaces for user layers.
> > These helper functions allow clients to pass data and select the
> > FF-A function to use for the communication with secure world.
> > 
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > +++ b/arch/arm/cpu/armv8/smccc-call.S
> > @@ -1,6 +1,8 @@
> >  /* SPDX-License-Identifier: GPL-2.0 */
> >  /*
> >   * Copyright (c) 2015, Linaro Limited
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  #include <linux/linkage.h>
> >  #include <linux/arm-smccc.h>
> > @@ -45,3 +47,28 @@ ENDPROC(__arm_smccc_smc)
> >  ENTRY(__arm_smccc_hvc)
> >  	SMCCC	hvc
> >  ENDPROC(__arm_smccc_hvc)
> > +
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +
> > +	.macro FFASMCCC instr
> > +	.cfi_startproc
> > +	\instr	#0
> > +	ldr	x9, [sp]
> > +	stp	x0, x1, [x9, #ARM_SMCCC_RES_X0_OFFS]
> > +	stp	x2, x3, [x9, #ARM_SMCCC_RES_X2_OFFS]
> > +	stp	x4, x5, [x9, #ARM_SMCCC_RES_X4_OFFS]
> > +	stp	x6, x7, [x9, #ARM_SMCCC_RES_X6_OFFS]
> > +	ret
> > +	.cfi_endproc
> > +	.endm
> > +
> > +/*
> > + * void arm_ffa_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
> > + *		  unsigned long a3, unsigned long a4, unsigned long a5,
> > + *		  unsigned long a6, unsigned long a7, struct arm_smccc_res *res)
> > + */
> > +ENTRY(__arm_ffa_smccc_smc)
> > +	FFASMCCC	smc
> > +ENDPROC(__arm_ffa_smccc_smc)
> > +
> > +#endif
> > diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
> > index 22fd541f9a..02a4a42fe6 100644
> > --- a/arch/arm/lib/asm-offsets.c
> > +++ b/arch/arm/lib/asm-offsets.c
> > @@ -9,6 +9,8 @@
> >   * generate asm statements containing #defines,
> >   * compile this file to assembler, and then extract the
> >   * #defines from the assembly-language output.
> > + *
> > + * (C) Copyright 2022 ARM Limited
> >   */
> >  
> >  #include <common.h>
> > @@ -115,6 +117,10 @@ int main(void)
> >  #ifdef CONFIG_ARM_SMCCC
> >  	DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
> >  	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +	DEFINE(ARM_SMCCC_RES_X4_OFFS, offsetof(struct arm_smccc_res, a4));
> > +	DEFINE(ARM_SMCCC_RES_X6_OFFS, offsetof(struct arm_smccc_res, a6));
> > +#endif
> >  	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
> >  	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
> >  #endif
> > diff --git a/common/board_r.c b/common/board_r.c
> > index b92c1bb0be..bb5f1d0aa6 100644
> > --- a/common/board_r.c
> > +++ b/common/board_r.c
> > @@ -62,6 +62,10 @@
> >  #include <asm-generic/gpio.h>
> >  #include <efi_loader.h>
> >  
> > +#ifdef CONFIG_ARM_FFA_TRANSPORT
> > +#include <arm_ffa_helper.h>
> > +#endif
> > +
> >  DECLARE_GLOBAL_DATA_PTR;
> >  
> >  ulong monitor_flash_len;
> > @@ -771,6 +775,9 @@ static init_fnc_t init_sequence_r[] = {
> >  	INIT_FUNC_WATCHDOG_RESET
> >  	initr_net,
> >  #endif
> > +#ifdef CONFIG_ARM_FFA_TRANSPORT
> > +	ffa_helper_bus_discover,
> > +#endif
> >  #ifdef CONFIG_POST
> >  	initr_post,
> >  #endif
> > diff --git a/drivers/Kconfig b/drivers/Kconfig
> > index b26ca8cf70..e83c23789d 100644
> > --- a/drivers/Kconfig
> > +++ b/drivers/Kconfig
> > @@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
> >  
> >  source "drivers/adc/Kconfig"
> >  
> > +source "drivers/arm-ffa/Kconfig"
> > +
> >  source "drivers/ata/Kconfig"
> >  
> >  source "drivers/axi/Kconfig"
> > diff --git a/drivers/Makefile b/drivers/Makefile
> > index 4e7cf28440..6671d2a604 100644
> > --- a/drivers/Makefile
> > +++ b/drivers/Makefile
> > @@ -107,6 +107,7 @@ obj-y += iommu/
> >  obj-y += smem/
> >  obj-y += thermal/
> >  obj-$(CONFIG_TEE) += tee/
> > +obj-$(CONFIG_ARM_FFA_TRANSPORT) += arm-ffa/
> >  obj-y += axi/
> >  obj-y += ufs/
> >  obj-$(CONFIG_W1) += w1/
> > diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
> > new file mode 100644
> > index 0000000000..23815534c4
> > --- /dev/null
> > +++ b/drivers/arm-ffa/Kconfig
> > @@ -0,0 +1,27 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +config ARM_FFA_TRANSPORT
> > +	bool "Enable Arm Firmware Framework for Armv8-A driver"
> > +	depends on DM && ARM64
> > +	select ARM_SMCCC if ARM64
> > +	select LIB_UUID
> > +	select ARM_FFA_TRANSPORT_HELPERS
> > +	help
> > +	  The Firmware Framework for Arm A-profile processors (FF-A)
> > +	  describes interfaces (ABIs) that standardize communication
> > +	  between the Secure World and Normal World leveraging TrustZone
> > +	  technology.
> > +
> > +	  This driver is based on FF-A specification v1.0 and uses SMC32
> > +	  calling convention.
> > +
> > +	  FF-A specification:
> > +
> > +	  https://developer.arm.com/documentation/den0077/a/?lang=en
> > +
> > +	  In u-boot FF-A design, FF-A is considered as a discoverable bus.
> > +	  The Secure World is considered as one entity to communicate with
> > +	  using the FF-A bus.
> > +	  FF-A communication is handled by one device and one instance (the bus).
> > +	  This FF-A driver takes care of all the interactions between Normal world
> > +	  and Secure World.
> > diff --git a/drivers/arm-ffa/Makefile b/drivers/arm-ffa/Makefile
> > new file mode 100644
> > index 0000000000..7bc9a336a9
> > --- /dev/null
> > +++ b/drivers/arm-ffa/Makefile
> > @@ -0,0 +1,6 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +#
> > +# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > +#
> > +
> > +obj-y += arm-ffa-uclass.o core.o
> > diff --git a/drivers/arm-ffa/arm-ffa-uclass.c b/drivers/arm-ffa/arm-ffa-uclass.c
> > new file mode 100644
> > index 0000000000..2439f87586
> > --- /dev/null
> > +++ b/drivers/arm-ffa/arm-ffa-uclass.c
> > @@ -0,0 +1,64 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <arm_ffa.h>
> > +#include <errno.h>
> > +#include <log.h>
> > +#include <asm/global_data.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +UCLASS_DRIVER(ffa) = {
> > +	.name		= "ffa",
> > +	.id		= UCLASS_FFA,
> > +};
> > +
> > +/**
> > + * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher
> > + * @func_id:	The FF-A function to be used
> > + * @func_data:  Pointer to the FF-A function arguments
> > + *				container structure. This also includes
> > + *				pointers to the returned data needed by
> > + *				clients.
> > + *
> > + * This runtime function passes the FF-A function ID and its arguments to
> > + * the FF-A driver dispatcher.
> > + * This function is called by the FF-A helper functions.
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +int __ffa_runtime ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *func_data)
> > +{
> > +	if (!ffa_device_get_ops()->invoke_func)
> > +		return -EINVAL;
> > +
> > +	return ffa_device_get_ops()->invoke_func(func_id, func_data);
> > +}
> > +
> > +/**
> > + * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
> > + *
> > + * This boot time function makes sure the FF-A bus is discoverable.
> > + * Then, the arm_ffa device is probed and ready to use.
> > + * This function is called automatically at initcalls
> > + * level (after u-boot relocation).
> > + *
> > + * Arm FF-A transport is implemented through arm_ffa u-boot device managing the FF-A
> > + * communication.
> > + * All FF-A clients should use the arm_ffa device to use the FF-A transport.
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +int ffa_bus_discover(void)
> > +{
> > +	return ffa_get_device();
> > +}
> > diff --git a/drivers/arm-ffa/arm_ffa_prv.h b/drivers/arm-ffa/arm_ffa_prv.h
> > new file mode 100644
> > index 0000000000..44f258addb
> > --- /dev/null
> > +++ b/drivers/arm-ffa/arm_ffa_prv.h
> > @@ -0,0 +1,193 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_PRV_H
> > +#define __ARM_FFA_PRV_H
> > +
> > +#include <arm_ffa.h>
> > +#include <linux/bitfield.h>
> > +#include <linux/bitops.h>
> > +#include <dm/read.h>
> > +
> > +/*
> > + * This header is private. It is exclusively used by the FF-A driver
> > + */
> > +
> > +/* FF-A core driver name */
> > +#define FFA_DRV_NAME "arm_ffa"
> > +
> > +/* FF-A driver version definitions */
> > +
> > +#define MAJOR_VERSION_MASK		GENMASK(30, 16)
> > +#define MINOR_VERSION_MASK		GENMASK(15, 0)
> > +#define GET_FFA_MAJOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> > +#define GET_FFA_MINOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> > +#define PACK_VERSION_INFO(major, minor)			\
> > +	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
> > +	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> > +
> > +#define FFA_MAJOR_VERSION		(1)
> > +#define FFA_MINOR_VERSION		(0)
> > +#define FFA_VERSION_1_0		\
> > +			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> > +
> > +/* Endpoint ID mask (u-boot endpoint ID) */
> > +
> > +#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define GET_SELF_ENDPOINT_ID(x)		\
> > +			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> > +
> > +#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
> > +#define PREP_SELF_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> > +
> > +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> > +
> > +#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define PREP_PART_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> > +
> > +/* The FF-A SMC function prototype definition */
> > +
> > +typedef void (*invoke_ffa_fn_t)(unsigned long a0, unsigned long a1,
> > +			unsigned long a2, unsigned long a3, unsigned long a4,
> > +			unsigned long a5, unsigned long a6, unsigned long a7,
> > +			struct arm_smccc_res *res);
> > +
> > +/**
> > + * enum ffa_conduit - Arm FF-A conduits supported by the Arm FF-A driver
> > + * Currently only SMC32 is supported.
> > + */
> > +enum ffa_conduit {
> > +	FFA_CONDUIT_SMC = 0,
> > +};
> > +
> > +/**
> > + * FFA_DECLARE_ARGS - FF-A functions local variables
> > + * @a0-a7:	local variables used to set registers x0-x7
> > + * @res:	the structure hosting the FF-A function return data
> > + *
> > + * A helper macro for declaring local variables for the FF-A functions  arguments.
> > + * The x0-x7 registers are used to exchange data with the secure world.
> > + * But, only the bottom 32-bit of thes registers contains the data.
> > + */
> > +#define FFA_DECLARE_ARGS \
> > +	unsigned long a0 = 0; \
> > +	unsigned long a1 = 0; \
> > +	unsigned long a2 = 0; \
> > +	unsigned long a3 = 0; \
> > +	unsigned long a4 = 0; \
> > +	unsigned long a5 = 0; \
> > +	unsigned long a6 = 0; \
> > +	unsigned long a7 = 0; \
> > +	struct arm_smccc_res res = {0}
> > +
> > +/* FF-A error codes */
> > +#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_INTERRUPTED				(-5)
> > +#define FFA_ERR_STAT_DENIED				(-6)
> > +#define FFA_ERR_STAT_RETRY				(-7)
> > +#define FFA_ERR_STAT_ABORTED				(-8)
> > +
> > +/**
> > + * struct ffa_features_desc - FF-A functions features
> > + * @func_id:	FF-A function
> > + * @field1:	features read from register w2
> > + * @field2:	features read from register w3
> > + *
> > + * Data structure describing the features of the  FF-A functions queried by
> > + * FFA_FEATURES
> > + */
> > +struct ffa_features_desc {
> > +	u32 func_id;
> > +	u32 field1;
> > +	u32 field2;
> > +};
> > +
> > +/**
> > + * enum ffa_rxtx_buf_sizes - minimum sizes supported
> > + * for the RX/TX buffers
> > + */
> > +enum ffa_rxtx_buf_sizes {
> > +	RXTX_4K,
> > +	RXTX_64K,
> > +	RXTX_16K
> > +};
> > +
> > +/*
> > + * Number of the FF-A interfaces features descriptors
> > + * currently only FFA_RXTX_MAP descriptor is supported
> > + */
> > +#define FFA_FEATURE_DESC_CNT (1)
> > +
> > +/**
> > + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> > + * @rxbuf:	virtual address of the RX buffer
> > + * @txbuf:	virtual address of the TX buffer
> > + *
> > + * Data structure hosting the virtual addresses of the mapped RX/TX buffers
> > + * These addresses are used by the FF-A functions that use the RX/TX buffers
> > + */
> > +struct ffa_rxtxpair {
> > +	u64 rxbuf; /* virtual address */
> > +	u64 txbuf; /* virtual address */
> > +};
> > +
> > +/**
> > + * struct ffa_partition_desc - the secure partition descriptor
> > + * @info:	partition information
> > + * @UUID:	UUID
> > + *
> > + * Each partition has its descriptor containing the partitions information and the UUID
> > + */
> > +struct ffa_partition_desc {
> > +	struct ffa_partition_info info;
> > +	union ffa_partition_uuid UUID;
> > +};
> > +
> > +/**
> > + * struct ffa_partitions - descriptors for all secure partitions
> > + * @count:	The number of partitions descriptors
> > + * @descs	The partitions descriptors table
> > + *
> > + * This data structure contains the partitions descriptors table
> > + */
> > +struct ffa_partitions {
> > +	u32 count;
> > +	struct ffa_partition_desc *descs; /* virtual address */
> > +};
> > +
> > +/**
> > + * struct 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
> > + * @conduit:	The selected conduit
> > + * @invoke_ffa_fn:	The function executing the FF-A function
> > + * @features:	Table of the FF-A functions having features
> > + *
> > + * The driver data structure hosting all resident data.
> > + */
> > +struct ffa_prvdata {
> > +	struct udevice *dev;
> > +	u32 fwk_version;
> > +	u16 id;
> > +	struct ffa_partitions partitions;
> > +	struct ffa_rxtxpair pair;
> > +	enum ffa_conduit conduit;
> > +	invoke_ffa_fn_t invoke_ffa_fn;
> > +	struct ffa_features_desc features[FFA_FEATURE_DESC_CNT];
> > +};
> > +
> > +#endif
> > diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c
> > new file mode 100644
> > index 0000000000..09e4eb753a
> > --- /dev/null
> > +++ b/drivers/arm-ffa/core.c
> > @@ -0,0 +1,1349 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include "arm_ffa_prv.h"
> > +#include <asm/global_data.h>
> > +#include <asm/io.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 <log.h>
> > +#include <malloc.h>
> > +#include <mapmem.h>
> > +#include <string.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/**
> > + * The device private data structure containing all the resident
> > + * data read from secure world
> > + */
> > +struct ffa_prvdata __ffa_runtime_data ffa_priv_data = {0};
> > +
> > +/*
> > + * Driver functions
> > + */
> > +
> > +/**
> > + * ffa_get_device - create, bind and probe the arm_ffa device
> > + *
> > + * This boot time function makes sure the arm_ffa device is
> > + * created, bound to this driver, probed and ready to use.
> > + * Arm FF-A transport is implemented through a single u-boot
> > + * device managing the FF-A bus (arm_ffa).
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +int ffa_get_device(void)
> > +{
> > +	int ret;
> > +
> > +	if (ffa_priv_data.dev)
> > +		return FFA_ERR_STAT_SUCCESS;
> > +
> > +	ret = device_bind(dm_root(),
> > +			  DM_DRIVER_GET(arm_ffa),
> > +			  FFA_DRV_NAME,
> > +			  NULL,
> > +			  ofnode_null(),
> > +			  &ffa_priv_data.dev);
> > +	if (ret) {
> > +		ffa_priv_data.dev = NULL;
> > +		return ret;
> > +	}
> > +
> > +	/* The FF-A bus discovery succeeds when probing is successful */
> > +	ret = device_probe(ffa_priv_data.dev);
> > +	if (ret) {
> > +		ffa_err("can not probe  the device");
> > +		device_unbind(ffa_priv_data.dev);
> > +		ffa_priv_data.dev = NULL;
> > +		return ret;
> > +	}
> > +
> > +	return FFA_ERR_STAT_SUCCESS;
> > +}
> > +
> > +/**
> > + * ffa_get_version - FFA_VERSION handler function
> > + *
> > + * This is the boot time function that implements FFA_VERSION FF-A function
> > + * to get from the secure world the FF-A framework version
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_get_version(void)
> > +{
> > +	u16 major, minor;
> > +
> > +	FFA_DECLARE_ARGS;
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	a0 = FFA_VERSION;
> > +	a1 = FFA_VERSION_1_0;
> > +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> > +
> > +	if (res.a0 == FFA_ERR_STAT_NOT_SUPPORTED) {
> > +		ffa_err("A Firmware Framework implementation does not exist");
> > +		return -EOPNOTSUPP;
> > +	}
> > +
> > +	major = GET_FFA_MAJOR_VERSION(res.a0);
> > +	minor = GET_FFA_MINOR_VERSION(res.a0);
> > +
> > +	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> > +		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
> > +		ffa_info("Versions are compatible ");
> > +
> > +		ffa_priv_data.fwk_version = res.a0;
> > +
> > +		return FFA_ERR_STAT_SUCCESS;
> > +	}
> > +
> > +	ffa_info("Versions are incompatible ");
> > +	return -EPROTONOSUPPORT;
> > +}
> > +
> > +/**
> > + * ffa_get_endpoint_id - FFA_ID_GET handler function
> > + *
> > + * This is the boot time function that implements FFA_ID_GET FF-A function
> > + * to get from the secure world u-boot endpoint ID
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_get_endpoint_id(void)
> > +{
> > +	FFA_DECLARE_ARGS;
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	a0 = FFA_ID_GET;
> > +
> > +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> > +
> > +	switch (res.a0) {
> > +	case FFA_ERROR:
> > +	{
> > +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
> > +			ffa_err("This function is not implemented at this FF-A instance");
> > +			return -EOPNOTSUPP;
> > +		}
> > +
> > +		ffa_err("Undefined error code (%d)", ((int)res.a2));
> > +		return -EINVAL;
> > +	}
> > +	case FFA_SUCCESS:
> > +	{
> > +		ffa_priv_data.id = GET_SELF_ENDPOINT_ID(res.a2);
> > +		ffa_info("endpoint ID is %u", ffa_priv_data.id);
> > +
> > +		return FFA_ERR_STAT_SUCCESS;
> > +	}
> > +	default:
> > +	{
> > +		ffa_err("Undefined response function (0x%lx)", res.a0);
> > +		return -EINVAL;
> > +	}
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_get_features_desc - returns the features descriptor of the specified
> > + *						FF-A function
> > + * @func_id:	the FF-A function which the features are to be retrieved
> > + *
> > + * This is a boot time function that searches the features descriptor of the
> > + * specified FF-A function
> > + *
> > + * Return:
> > + *
> > + * When found, the address of the features descriptor is returned. Otherwise, NULL.
> > + */
> > +static struct ffa_features_desc *ffa_get_features_desc(u32 func_id)
> > +{
> > +	u32 desc_idx;
> > +
> > +	/*
> > +	 * search for the descriptor of the selected FF-A interface
> > +	 */
> > +	for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
> > +		if (ffa_priv_data.features[desc_idx].func_id == func_id)
> > +			return &ffa_priv_data.features[desc_idx];
> > +
> > +	return NULL;
> > +}
> > +
> > +/**
> > + * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP
> > + *							argument
> > + *
> > + * This is the boot time function that implements FFA_FEATURES FF-A function
> > + * to retrieve the FFA_RXTX_MAP features
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_get_rxtx_map_features(void)
> > +{
> > +	FFA_DECLARE_ARGS;
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	a0 = FFA_FEATURES;
> > +	a1 = FFA_RXTX_MAP;
> > +
> > +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> > +
> > +	switch (res.a0) {
> > +	case FFA_ERROR:
> > +	{
> > +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
> > +			ffa_err("FFA_RXTX_MAP is not implemented at this FF-A instance");
> > +			return -EOPNOTSUPP;
> > +		}
> > +
> > +		ffa_err("Undefined error code (%d)", ((int)res.a2));
> > +		return -EINVAL;
> 
> This happens quite a few times throughout the code.  Why is -EINVAL used
> here instead of -FFA_ERR_STAT_INVALID_PARAMETERS for example?
> 
> We should either use FFA_* errors consistently of get rid of those entirely
> and stick to standard ones,  but let's not mix and match

Thanks for all your feedbacks.  Error handling and panics removal  have been addressed in v4 patchset. Now we use a mapping mechanism and no panics anymore.
please check: https://lore.kernel.org/all/20220926101723.9965-5-abdellatif.elkhlifi@arm.com/

> 
> > +	}
> > +	case FFA_SUCCESS:
> > +	{
> > +		u32 desc_idx;
> > +
> > +		/*
> > +		 * search for an empty descriptor
> > +		 */
> > +		for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
> > +			if (!ffa_priv_data.features[desc_idx].func_id) {
> > +				/*
> > +				 * populate the descriptor with
> > +				 * the interface features data
> > +				 */
> > +				ffa_priv_data.features[desc_idx].func_id =
> > +					FFA_RXTX_MAP;
> > +				ffa_priv_data.features[desc_idx].field1 =
> > +					res.a2;
> > +
> > +				ffa_info("FFA_RXTX_MAP features data 0x%lx",
> > +					 res.a2);
> > +
> > +				return FFA_ERR_STAT_SUCCESS;
> > +			}
> > +
> > +		ffa_err("Cannot save FFA_RXTX_MAP features data. Descriptors table full");
> > +		return -ENOBUFS;
> 
> Similarly -FFA_ERR_STAT_NO_MEMORY or something?
> 
> > +	}
> > +	default:
> > +	{
> > +		ffa_err("Undefined response function (0x%lx)",
> > +			res.a0);
> > +		return -EINVAL;
> > +	}
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_get_rxtx_buffers_pages_cnt - reads from the features data descriptors
> > + *						the minimum number of pages in each of the RX/TX
> > + *						buffers
> > + * @buf_4k_pages: Pointer to the minimum number of pages
> > + *
> > + * This is the boot time function that  returns the minimum number of pages
> > + *  in each of the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * buf_4k_pages points to the returned number of pages
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_get_rxtx_buffers_pages_cnt(size_t *buf_4k_pages)
> > +{
> > +	struct ffa_features_desc *desc = NULL;
> > +
> > +	if (!buf_4k_pages)
> > +		return -EINVAL;
> > +
> > +	desc = ffa_get_features_desc(FFA_RXTX_MAP);
> > +	if (!desc)
> > +		return -EINVAL;
> > +
> > +	switch (desc->field1) {
> > +	case RXTX_4K:
> > +		*buf_4k_pages = 1;
> > +		break;
> > +	case RXTX_16K:
> > +		*buf_4k_pages = 4;
> > +		break;
> > +	case RXTX_64K:
> > +		*buf_4k_pages = 16;
> > +		break;
> > +	default:
> > +		ffa_err("RX/TX buffer size not supported");
> > +		return -EINVAL;
> > +	}
> > +
> > +	return FFA_ERR_STAT_SUCCESS;
> > +}
> > +
> > +/**
> > + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> > + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> > + *			  buffers
> > + *
> > + * This is the boot time function used to free the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_free_rxtx_buffers(size_t buf_4k_pages)
> > +{
> > +	efi_status_t free_rxbuf_ret, free_txbuf_ret;
> > +
> > +	ffa_info("Freeing RX/TX buffers");
> > +
> > +	free_rxbuf_ret = efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
> > +	free_txbuf_ret = efi_free_pages(ffa_priv_data.pair.txbuf, buf_4k_pages);
> > +
> > +	if (free_rxbuf_ret != EFI_SUCCESS || free_txbuf_ret != EFI_SUCCESS) {
> > +		ffa_err("Failed to free RX/TX buffers (rx: %lu , tx: %lu)",
> > +			free_rxbuf_ret,
> > +			free_txbuf_ret);
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_priv_data.pair.rxbuf = 0;
> > +	ffa_priv_data.pair.txbuf = 0;
> 
> Should those be set to 0 regardless of the efi_free_pages() outcome? If not
> then you probably need to handle those one by one.  As is it right now one
> failure to free a buffer means both of those won't be set
> 

addressed in v4 patchset, please check: https://lore.kernel.org/all/20220926101723.9965-5-abdellatif.elkhlifi@arm.com/

> > +
> > +	return FFA_ERR_STAT_SUCCESS;
> > +}
> > +
> > +/**
> > + * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
> > + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> > + *			  buffers
> > + *
> > + * This is the boot time function used by ffa_map_rxtx_buffers to allocate
> > + * the RX/TX buffers before mapping them
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_alloc_rxtx_buffers(size_t buf_4k_pages)
> > +{
> > +#if CONFIG_IS_ENABLED(EFI_LOADER)
> > +
> > +	efi_status_t efi_ret;
> > +	void *virt_txbuf;
> > +	void *virt_rxbuf;
> > +
> > +	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
> > +		 buf_4k_pages);
> > +
> > +	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> > +				     EFI_BOOT_SERVICES_DATA,
> > +				     buf_4k_pages,
> > +				     &ffa_priv_data.pair.rxbuf);
> > +
> 
> Why are we specifically limiting this to EFI?  I understand using efi
> allocated memory for potential runtime operations, were we need the memory
> preserved, but why here?
> 
> There's also a side effect with this allocation.  The EFI subsystem doesn't
> usually come up until u-boot is fully up and running.  This call will force 
> it to start way earlier
> 

In v4 the core driver is no longer dependent on EFI. The intent is to be able to compile it
without EFI support. The use of EFI APIs has been dropped and replaced with generic u-boot
APIs.
When using EFI, FF-A core driver data needs to be copied to the EFI runtime section so it can be
accessed at runtime. For that specific case, a new CONFIG_ARM_FFA_EFI_RUNTIME_MODE
has been created to enable the feature of copying the data to the runtime section.
The code that copies the data is provided by drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
When EFI is needed CONFIG_ARM_FFA_EFI_RUNTIME_MODE should be turned on. If no EFI needed
the FF-A driver can still be used independently.

> > +	if (efi_ret != EFI_SUCCESS) {
> > +		ffa_priv_data.pair.rxbuf = 0;
> > +		ffa_err("Failure to allocate RX buffer (EFI error: 0x%lx)",
> > +			efi_ret);
> > +
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("RX buffer at virtual address 0x%llx",
> > +		 ffa_priv_data.pair.rxbuf);
> > +
> > +	virt_rxbuf = (void *)ffa_priv_data.pair.rxbuf;
> > +
> > +	/*
> > +	 * make sure the buffer is clean before use
> > +	 */
> > +	memset(virt_rxbuf, 0, buf_4k_pages * SZ_4K);
> > +
> > +	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> > +				     EFI_RUNTIME_SERVICES_DATA,
> > +				     buf_4k_pages,
> > +				     &ffa_priv_data.pair.txbuf);
> > +
> > +	if (efi_ret != EFI_SUCCESS) {
> > +		efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
> > +		ffa_priv_data.pair.rxbuf = 0;
> > +		ffa_priv_data.pair.txbuf = 0;
> > +		ffa_err("Failure to allocate the TX buffer (EFI error: 0x%lx)"
> > +			, efi_ret);
> > +
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("TX buffer at virtual address 0x%llx",
> > +		 ffa_priv_data.pair.txbuf);
> > +
> > +	virt_txbuf = (void *)ffa_priv_data.pair.txbuf;
> > +
> > +	/*
> > +	 * make sure the buffer is clean before use
> > +	 */
> > +	memset(virt_txbuf, 0, buf_4k_pages * SZ_4K);
> > +
> > +	return FFA_ERR_STAT_SUCCESS;
> > +
> > +#else
> > +	return -ENOBUFS;
> > +#endif
> > +}
> > +
> > +/**
> > + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> > + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> > + *			  buffers
> > + *
> > + * This is the boot time function that implements FFA_RXTX_MAP FF-A function
> > + * to map the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_map_rxtx_buffers(size_t buf_4k_pages)
> > +{
> > +	int ret;
> > +
> > +	FFA_DECLARE_ARGS;
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	ret = ffa_alloc_rxtx_buffers(buf_4k_pages);
> > +	if (ret != FFA_ERR_STAT_SUCCESS)
> > +		return ret;
> > +
> > +	a0 = FFA_RXTX_MAP;
> > +	a1 = ffa_priv_data.pair.txbuf;
> > +	a2 = ffa_priv_data.pair.rxbuf;
> > +	a3 = buf_4k_pages;
> > +
> > +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> > +
> > +	switch (res.a0) {
> > +	case FFA_ERROR:
> > +	{
> > +		switch (((int)res.a2)) {
> > +		case FFA_ERR_STAT_INVALID_PARAMETERS:
> > +			ffa_err("One or more fields in input parameters is incorrectly encoded");
> > +			ret = -EPERM;
> > +			break;
> > +		case FFA_ERR_STAT_NO_MEMORY:
> > +			ffa_err("Not enough memory");
> > +			ret = -ENOMEM;
> > +			break;
> > +		case FFA_ERR_STAT_DENIED:
> > +			ffa_err("Buffer pair already registered");
> > +			ret = -EACCES;
> > +			break;
> > +		case FFA_ERR_STAT_NOT_SUPPORTED:
> > +			ffa_err("This function is not implemented at this FF-A instance");
> > +			ret = -EOPNOTSUPP;
> > +			break;
> > +		default:
> > +			ffa_err("Undefined error (%d)",
> > +				((int)res.a2));
> > +			ret = -EINVAL;
> > +		}
> 
> Can we have an array with string literals for the errors and do a
> lookup instead of nested case switches?
> 
> > +		break;
> > +	}
> > +	case FFA_SUCCESS:
> > +		ffa_info("RX/TX buffers mapped");
> > +		return FFA_ERR_STAT_SUCCESS;
> > +	default:
> > +		ffa_err("Undefined response function (0x%lx)",
> > +			res.a0);
> > +		ret = -EINVAL;
> > +	}
> > +
> > +	ffa_free_rxtx_buffers(buf_4k_pages);
> > +
> > +	return ret;
> > +}
> > +
> > +/**
> > + * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
> > + *
> > + * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function
> > + * to unmap the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_unmap_rxtx_buffers(void)
> > +{
> > +	FFA_DECLARE_ARGS;
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	a0 = FFA_RXTX_UNMAP;
> > +	a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id);
> > +
> > +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> > +
> > +	switch (res.a0) {
> > +	case FFA_ERROR:
> > +	{
> > +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
> > +			panic("[FFA] FFA_RXTX_UNMAP is not implemented at this FF-A instance\n");
> > +		else if (((int)res.a2) == FFA_ERR_STAT_INVALID_PARAMETERS)
> > +			panic("[FFA] There is no buffer pair registered on behalf of the caller\n");
> > +		else
> > +			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
> 
> There's panics sprinkled around the code.  Are all those cases really
> fatal?
> 
> > +	}
> > +	case FFA_SUCCESS:
> > +	{
> > +		size_t buf_4k_pages = 0;
> > +		int ret;
> > +
> > +		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
> > +		if (ret != FFA_ERR_STAT_SUCCESS)
> > +			panic("[FFA] RX/TX buffers unmapped but failure in getting pages count\n");
> > +
> > +		ret = ffa_free_rxtx_buffers(buf_4k_pages);
> > +		if (ret != FFA_ERR_STAT_SUCCESS)
> > +			panic("[FFA] RX/TX buffers unmapped but failure in freeing the memory\n");
> > +
> > +		ffa_info("RX/TX buffers unmapped and memory freed");
> > +
> > +		return FFA_ERR_STAT_SUCCESS;
> > +	}
> > +	default:
> > +		panic("[FFA] Undefined response function (0x%lx)", res.a0);
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
> > + *
> > + * This is the boot time function that invokes FFA_RX_RELEASE FF-A function
> > + * to release the ownership of the RX buffer
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_release_rx_buffer(void)
> > +{
> > +	FFA_DECLARE_ARGS;
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	a0 = FFA_RX_RELEASE;
> > +
> > +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> > +
> > +	switch (res.a0) {
> > +	case FFA_ERROR:
> > +	{
> > +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
> > +			panic("[FFA] FFA_RX_RELEASE is not implemented at this FF-A instance\n");
> > +		else if (((int)res.a2) == FFA_ERR_STAT_DENIED)
> > +			panic("[FFA] Caller did not have ownership of the RX buffer\n");
> > +		else
> > +			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
> > +	}
> > +	case FFA_SUCCESS:
> > +		return FFA_ERR_STAT_SUCCESS;
> > +
> > +	default:
> > +		panic("[FFA] Undefined response function (0x%lx)\n", res.a0);
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_uuid_are_identical - checks whether two given UUIDs are identical
> > + * @uuid1: first UUID
> > + * @uuid2: second UUID
> > + *
> > + * This is a boot time function used by ffa_read_partitions_info to search
> > + * for a UUID in the partitions descriptors table
> > + *
> > + * Return:
> > + *
> > + * 1 when UUIDs match. Otherwise, 0
> > + */
> > +int ffa_uuid_are_identical(const union ffa_partition_uuid *uuid1,
> > +			   const union ffa_partition_uuid *uuid2)
> > +{
> > +	if (!uuid1 || !uuid2)
> > +		return 0;
> > +
> > +	return (!memcmp(uuid1, uuid2, sizeof(union ffa_partition_uuid)));
> > +}
> > +
> > +/**
> > + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> > + *							and saves it in the private structure
> > + * @count: The number of partitions queried
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + *
> > + * This is the boot time function that reads the partitions information
> > + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> > + * data structure.
> > + *
> > + * Return:
> > + *
> > + * The private data structure is updated with the partition(s) information
> > + * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
> > + */
> > +static int ffa_read_partitions_info(u32 count, union ffa_partition_uuid *part_uuid)
> > +{
> > +	if (!count) {
> > +		ffa_err("No partition detected");
> > +		return -ENODATA;
> > +	}
> > +
> > +	ffa_info("Reading partitions data from the RX buffer");
> > +
> > +#if CONFIG_IS_ENABLED(EFI_LOADER)
> > +
> > +	if (!part_uuid) {
> > +		/*
> > +		 * querying information of all partitions
> > +		 */
> > +		u64 data_pages;
> > +		u64 data_bytes;
> > +		efi_status_t efi_ret;
> > +		size_t buf_4k_pages = 0;
> > +		u32 desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +		int ret;
> > +
> > +		data_bytes = count * sizeof(struct ffa_partition_desc);
> > +		data_pages = efi_size_in_pages(data_bytes);
> > +
> > +		/*
> > +		 * get the RX buffer size in pages
> > +		 */
> > +		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
> > +		if (ret != FFA_ERR_STAT_SUCCESS) {
> > +			ffa_err("Can not get the RX buffer size (error %d)", ret);
> > +			return ret;
> > +		}
> > +
> > +		if (data_pages > buf_4k_pages) {
> > +			ffa_err("Partitions data size exceeds the RX buffer size:");
> > +			ffa_err("    Sizes in pages: data %llu , RX buffer %lu ",
> > +				data_pages,
> > +				buf_4k_pages);
> > +
> > +			return -ENOMEM;
> > +		}
> > +
> > +		efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> > +					     EFI_RUNTIME_SERVICES_DATA,
> > +					     data_pages,
> > +					     (u64 *)&ffa_priv_data.partitions.descs);
> > +
> 
> Same questions here.  Why are we using the EFI APIs to allocate buffers?
> 
> > +		if (efi_ret != EFI_SUCCESS) {
> > +			ffa_priv_data.partitions.descs = NULL;
> > +
> > +			ffa_err("Cannot  allocate partitions data buffer (EFI error 0x%lx)",
> > +				efi_ret);
> > +
> > +			return -ENOBUFS;
> > +		}
> > +
> > +		/*
> > +		 * make sure the buffer is clean before use
> > +		 */
> > +		memset(ffa_priv_data.partitions.descs, 0,
> > +		       data_pages * SZ_4K);
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data.pair.rxbuf;
> > +
> > +		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
> > +			ffa_priv_data.partitions.descs[desc_idx].info =
> > +				parts_info[desc_idx];
> > +
> > +			ffa_info("Partition ID %x : info cached",
> > +				 ffa_priv_data.partitions.descs[desc_idx].info.id);
> > +		}
> > +
> > +		ffa_priv_data.partitions.count = count;
> > +
> > +		ffa_info("%d partition(s) found and cached", count);
> > +
> > +	} else {
> > +		u32 rx_desc_idx, cached_desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +		u8 desc_found;
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data.pair.rxbuf;
> > +
> > +		/*
> > +		 * search for the SP IDs read from the RX buffer
> > +		 * in the already cached SPs.
> > +		 * Update the UUID when ID found.
> > +		 */
> > +		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
> > +			desc_found = 0;
> > +
> > +			/*
> > +			 * search the current ID in the cached partitions
> > +			 */
> > +			for (cached_desc_idx = 0;
> > +			     cached_desc_idx < ffa_priv_data.partitions.count;
> > +			     cached_desc_idx++) {
> > +				/*
> > +				 * save the UUID
> > +				 */
> > +				if (ffa_priv_data.partitions.descs[cached_desc_idx].info.id ==
> > +				    parts_info[rx_desc_idx].id) {
> > +					ffa_priv_data.partitions.descs[cached_desc_idx].UUID =
> > +						*part_uuid;
> > +
> > +					desc_found = 1;
> > +					break;
> > +				}
> > +			}
> > +
> > +			if (!desc_found)
> > +				return -ENODATA;
> > +		}
> > +	}
> > +#else
> > +#warning "arm_ffa: reading FFA_PARTITION_INFO_GET data not implemented"
> > +#endif
> > +
> > +	return  FFA_ERR_STAT_SUCCESS;
> > +}
> > +
> > +/**
> > + * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET
> > + *							and saves partitions data
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + * @pcount: Pointer to the number of partitions variable filled when querying
> > + *
> > + * This is the boot time function that executes the FFA_PARTITION_INFO_GET
> > + * to query the partitions data. Then, it calls ffa_read_partitions_info
> > + * to save the data in the private data structure.
> > + *
> > + * After reading the data the RX buffer is released using ffa_release_rx_buffer
> > + *
> > + * Return:
> > + *
> > + * When part_uuid is NULL, all partitions data are retrieved from secure world
> > + * When part_uuid is non NULL, data for partitions matching the given UUID are
> > + * retrieved and the number of partitions is returned
> > + * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
> > + */
> > +static int ffa_query_partitions_info(union ffa_partition_uuid *part_uuid,
> > +				     u32 *pcount)
> > +{
> > +	unsigned long a0 = 0;
> > +	union ffa_partition_uuid query_uuid = {0};
> > +	unsigned long a5 = 0;
> > +	unsigned long a6 = 0;
> > +	unsigned long a7 = 0;
> > +	struct arm_smccc_res res = {0};
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	a0 = FFA_PARTITION_INFO_GET;
> > +
> > +	/*
> > +	 * If a UUID is specified. Information for one or more
> > +	 * partitions in the system is queried. Otherwise, information
> > +	 * for all installed partitions is queried
> > +	 */
> > +
> > +	if (part_uuid) {
> > +		if (!pcount)
> > +			return -EINVAL;
> > +
> > +		query_uuid = *part_uuid;
> > +	}
> > +
> > +	ffa_priv_data.invoke_ffa_fn(a0, query_uuid.words.a1, query_uuid.words.a2,
> > +				    query_uuid.words.a3, query_uuid.words.a4,
> > +				    a5, a6, a7, &res);
> > +
> > +	switch (res.a0) {
> > +	case FFA_ERROR:
> > +	{
> > +		switch (((int)res.a2)) {
> > +		case FFA_ERR_STAT_INVALID_PARAMETERS:
> > +			ffa_err("Unrecognized UUID");
> > +			return -EPERM;
> > +		case FFA_ERR_STAT_NO_MEMORY:
> > +			ffa_err("Results cannot fit in RX buffer of the caller");
> > +			return -ENOMEM;
> > +		case FFA_ERR_STAT_DENIED:
> > +			ffa_err("Callee is not in a state to handle this request");
> > +			return -EACCES;
> > +		case FFA_ERR_STAT_NOT_SUPPORTED:
> > +			ffa_err("This function is not implemented at this FF-A instance");
> > +			return -EOPNOTSUPP;
> > +		case FFA_ERR_STAT_BUSY:
> > +			ffa_err("RX buffer of the caller is not free");
> > +			return -EBUSY;
> > +		default:
> > +			ffa_err("Undefined error (%d)", ((int)res.a2));
> > +			return -EINVAL;
> > +		}
> > +	}
> 
> Same cases as above. Please map those in an array or something and just do
> a lookup to print an error
> 
> > +	case FFA_SUCCESS:
> > +	{
> > +		int ret;
> > +
> > +		/*
> > +		 * res.a2 contains the count of partition information descriptors
> > +		 * populated in the RX buffer
> > +		 */
> > +		if (res.a2) {
> > +			ret = ffa_read_partitions_info(res.a2, part_uuid);
> > +			if (ret)
> > +				ffa_err("Failed to read partition(s) data , error (%d)", ret);
> > +		}
> > +
> > +		/*
> > +		 * return the SP count
> > +		 */
> > +		if (part_uuid) {
> > +			if (!ret)
> > +				*pcount = res.a2;
> > +			else
> > +				*pcount = 0;
> > +		}
> 
> If I am following the code correctly this can be called with (NULL, NULL),
> which means that the previous !pcount check won't apply.  Is there any
> other check I am missing?
> 

addressed in v4 patchset, please check: https://lore.kernel.org/all/20220926101723.9965-5-abdellatif.elkhlifi@arm.com/

> > +		/*
> > +		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
> > +		 * is assigned to the consumer (u-boot). So, we need to give
> > +		 * the ownership back to the secure world
> > +		 */
> > +		ret = ffa_release_rx_buffer();
> > +
> > +		if (!part_uuid && !res.a2) {
> > +			ffa_err("[FFA] no partition installed in the system");
> > +			return -ENODEV;
> > +		}
> > +
> > +		return ret;
> > +	}
> > +	default:
> > +		ffa_err("Undefined response function (0x%lx)", res.a0);
> > +		return  -EINVAL;
> > +	}
> > +}
> > +
> > +/**
>  
> [...]
> 
> Regards
> /Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 6/6] arm_ffa: introduce FF-A MM communication
  2022-04-14 19:54   ` Ilias Apalodimas
@ 2022-09-26 10:56     ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 10:56 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, nd

On Thu, Apr 14, 2022 at 10:54:08PM +0300, Ilias Apalodimas wrote:
> Hi Abdellatif, 
> 
> Can you please keep me cc'ed in future revisions?
> 
> On Tue, Mar 29, 2022 at 04:16:59PM +0100, abdellatif.elkhlifi@arm.com wrote:
> > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > 
> > Add MM communication support using FF-A transport
> > 
> > FF-A MM communication allows exchanging data with StandAlonneMM
> > or smm-gateway secure partitions which run in OP-TEE.
> > 
> > An MM shared buffer and a door bell event are used to exchange
> > this data.
> > 
> > The data is used by EFI services such as GetVariable()/SetVariable()
> >  and copied from the communication buffer to the MM shared buffer.
> > 
> > The secure partition is notified about availability of data in the
> >  MM shared buffer by an FF-A message (door bell).
> > 
> > On such event, MM SP can read the data and updates the MM shared
> >  buffer with the response data.
> > 
> > The response data is copied back to the communication buffer and
> >  consumed by the EFI subsystem.
> 
> What I am missing from all this is a description on how to test this and
> what's needed in OP-TEE and EDK2.
> 
> Unless I am reading this wrong, there is a "new" Secure Partition that will
> handle both the efi variables (along with all the EFI rules you need to update
> those and the crypto checks you need for authenticated variables). But StMM
> includes the hardware drivers as well. How is that handled in the SP
> context?
> 

In the v4 patchset the MM SPs are discovered at runtime. All MM SPs have the same UUID
and use the same communication protocol. From v4, FF-A MM communication in u-boot is not tied to
any MM SP. Please check: https://lore.kernel.org/all/20220926101723.9965-10-abdellatif.elkhlifi@arm.com/

> > 
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
> > Cc: Tom Rini <trini@konsulko.com>
> > ---
> >  arch/arm/cpu/armv8/cache.S        |  16 ++
> >  arch/arm/cpu/armv8/cache_v8.c     |   3 +-
> >  include/mm_communication.h        |   4 +-
> >  lib/efi_loader/Kconfig            |  14 +-
> >  lib/efi_loader/efi_variable_tee.c | 294 +++++++++++++++++++++++++++++-
> >  5 files changed, 321 insertions(+), 10 deletions(-)
> > 
> > diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S
> > index d1cee23437..bdbe89e0c5 100644
> > --- a/arch/arm/cpu/armv8/cache.S
> > +++ b/arch/arm/cpu/armv8/cache.S
> > @@ -21,7 +21,11 @@
> >   * x1: 0 clean & invalidate, 1 invalidate only
> >   * x2~x9: clobbered
> >   */
> > +#ifdef CONFIG_ARM_FFA_TRANSPORT
> > +.pushsection .text.efi_runtime, "ax"
> > +#else
> >  .pushsection .text.__asm_dcache_level, "ax"
> > +#endif
> >  ENTRY(__asm_dcache_level)
> >  	lsl	x12, x0, #1
> >  	msr	csselr_el1, x12		/* select cache level */
> > @@ -65,7 +69,11 @@ ENDPROC(__asm_dcache_level)
> >   *
> >   * flush or invalidate all data cache by SET/WAY.
> >   */
> > +#ifdef CONFIG_ARM_FFA_TRANSPORT
> > +.pushsection .text.efi_runtime, "ax"
> > +#else
> >  .pushsection .text.__asm_dcache_all, "ax"
> > +#endif
> >  ENTRY(__asm_dcache_all)
> >  	mov	x1, x0
> >  	dsb	sy
> > @@ -109,7 +117,11 @@ ENTRY(__asm_flush_dcache_all)
> >  ENDPROC(__asm_flush_dcache_all)
> >  .popsection
> >  
> > +#ifdef CONFIG_ARM_FFA_TRANSPORT
> > +.pushsection .text.efi_runtime, "ax"
> > +#else
> >  .pushsection .text.__asm_invalidate_dcache_all, "ax"
> > +#endif
> >  ENTRY(__asm_invalidate_dcache_all)
> >  	mov	x0, #0x1
> >  	b	__asm_dcache_all
> > @@ -182,7 +194,11 @@ ENTRY(__asm_invalidate_icache_all)
> >  ENDPROC(__asm_invalidate_icache_all)
> >  .popsection
> >  
> > +#ifdef CONFIG_ARM_FFA_TRANSPORT
> > +.pushsection .text.efi_runtime, "ax"
> > +#else
> >  .pushsection .text.__asm_invalidate_l3_dcache, "ax"
> > +#endif
> >  WEAK(__asm_invalidate_l3_dcache)
> >  	mov	x0, #0			/* return status as success */
> >  	ret
> > diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
> > index 3de18c7675..187a4497a7 100644
> > --- a/arch/arm/cpu/armv8/cache_v8.c
> > +++ b/arch/arm/cpu/armv8/cache_v8.c
> > @@ -9,6 +9,7 @@
> >  
> >  #include <common.h>
> >  #include <cpu_func.h>
> > +#include <efi_loader.h>
> >  #include <hang.h>
> >  #include <log.h>
> >  #include <asm/cache.h>
> > @@ -425,7 +426,7 @@ __weak void mmu_setup(void)
> >  /*
> >   * Performs a invalidation of the entire data cache at all levels
> >   */
> > -void invalidate_dcache_all(void)
> > +void __efi_runtime invalidate_dcache_all(void)
> >  {
> >  	__asm_invalidate_dcache_all();
> >  	__asm_invalidate_l3_dcache();
> > diff --git a/include/mm_communication.h b/include/mm_communication.h
> > index e65fbde60d..bb99190956 100644
> > --- a/include/mm_communication.h
> > +++ b/include/mm_communication.h
> > @@ -123,7 +123,7 @@ struct __packed efi_mm_communicate_header {
> >   *
> >   * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_HEADER.
> >   */
> > -struct smm_variable_communicate_header {
> > +struct __packed smm_variable_communicate_header {
> 
> Why is this converted to packed?
> 

no need to add the attribute packed for efi_mm_communicate_header and 
smm_variable_communicate_header structures because all fields sizes are
multiple of 8 bytes. This has been addressed in v4 patchset.
However, the smm_variable_access structure still needs to be packed
because attr is u32 and a 4 bytes padding is added by the compiler
which breaks the communication with the secure world.

> >  	efi_uintn_t  function;
> >  	efi_status_t ret_status;
> >  	u8           data[];
> > @@ -145,7 +145,7 @@ struct smm_variable_communicate_header {
> >   * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
> >   *
> >   */
> > -struct smm_variable_access {
> > +struct __packed smm_variable_access {
> 
> Ditto
> 
> >  	efi_guid_t  guid;
> >  	efi_uintn_t data_size;
> >  	efi_uintn_t name_size;
> > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > index 28657f50c9..0d69133595 100644
> > --- a/lib/efi_loader/Kconfig
> > +++ b/lib/efi_loader/Kconfig
> > @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
> >  	  stored as file /ubootefi.var on the EFI system partition.
> >  
> >  config EFI_MM_COMM_TEE
> > -	bool "UEFI variables storage service via OP-TEE"
> > -	depends on OPTEE
> > +	bool "UEFI variables storage service via the trusted world"
> > +	depends on OPTEE || ARM_FFA_TRANSPORT
> >  	help
> > +	  The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
> > +	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> > +	  When using the u-boot FF-A  driver, StandAlonneMM and smm-gateway are supported.
> > +
> >  	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
> >  	  variable related operations to that. The application will verify,
> >  	  authenticate and store the variables on an RPMB.
> >  
> > +	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> > +	  operations to the MM SP running under Optee in the trusted world.
> > +	  A door bell mechanism is used to notify the SP when there is data in the shared
> > +	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
> > +	  the door bell event.
> > +
> 
> The naming is a bit misleading imho.  FF-A is the transport mechanism between the
> secure and non-secure world. You may as well have FF-A along with OP-TEE.
> That doesn't automatically mean the SP is used instead of StMM.
> 
> This code is complicated already, I don't think we want the additional
> ifdefery.  Wouldn't it be better to have this discover to what kind of
> protocol (e.g FF-A vs SMC calling conventions) it talks to?  SPs are
> discoverable,  so we could reason about those as well without asking the
> user to understand Arm protocol internals. 
> 

From patchset v4, when using the u-boot FF-A driver all MM SPs are supported
because the agreement is that they all use the same UUID.
Please check: https://lore.kernel.org/all/20220926101723.9965-10-abdellatif.elkhlifi@arm.com/

> >  endchoice
> >  
> >  config EFI_VARIABLES_PRESEED
> > diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> > index dfef18435d..3d01985662 100644
> > --- a/lib/efi_loader/efi_variable_tee.c
> > +++ b/lib/efi_loader/efi_variable_tee.c
> > @@ -15,6 +15,53 @@
> >  #include <malloc.h>
> >  #include <mm_communication.h>
> >  
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +
> > +#include <arm_ffa_helper.h>
> > +#include <cpu_func.h>
> > +#include <mapmem.h>
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> > +
> > +#include <linux/sizes.h>
> > +#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
> > +
> > +#endif
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> > +
> > +/*
> > + * shared buffer physical address used for communication between
> > + * u-boot and the MM SP
> > + */
> > +#define FFA_SHARED_MM_BUFFER_ADDR	(0x023F8000)
> 
> Can you explain what this is used for ?
> 

FF-A MM communication is implemented by ffa_mm_communicate(). 
It allows exchanging EFI services data with  the MM partition 
using FF-A transport. The mechanism is based on a shared buffer 
and a door bell event.

When u-boot wants to send data to the MM partition the data is
written to the shared buffer and a door bell event is issued.

A door bell event means that there is data to read from the 
shared buffer.

The MM partition writes its response in the same shared buffer 
and u-boot reads the response from the shared buffer at 
ffa_mm_communicate() level.

The shared buffer address is specified by 
FFA_SHARED_MM_BUFFER_ADDR and should be defined by the board.

> > +
> > +#endif
> > +
> > +/* MM return codes */
> > +#define MM_SUCCESS (0)
> > +
> > +#define ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64 (0xC4000061)
> > +#define ARM_SVC_ID_SP_EVENT_COMPLETE ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64
> > +
> > +#ifndef MM_SP_UUID_DATA
> > +
> > +/* MM SP UUID binary data (little-endian format) */
> > +#define MM_SP_UUID_DATA	\
> > +	0xed, 0x32, 0xd5, 0x33,	\
> > +	0x99, 0xe6, 0x42, 0x09,	\
> > +	0x9c, 0xc0, 0x2d, 0x72,	\
> > +	0xcd, 0xd9, 0x98, 0xa7
> 
> [...]
> 
> > +
> > +	/* Announce there is data in the shared buffer */
> > +
> > +	ffa_ret = ffa_notify_mm_sp();
> > +	if (ffa_ret)
> > +		unmap_sysmem(virt_shared_buf);
> 
> There are several calls around on runtime code which call functions not
> marked as runtime.  This will just crash when called.
> 

This has been addressed from v2 patchset. Please refer to the latest work 
on v4: https://lore.kernel.org/all/20220926101723.9965-10-abdellatif.elkhlifi@arm.com/

> > +
> > +	switch (ffa_ret) {
> > +	case 0:
> > +	{
> > +		ulong rx_data_size;
> > +		/* Copy the MM SP response from the shared buffer to the communication buffer */
> > +		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> > +			sizeof(efi_guid_t) +
> > +			sizeof(size_t);
> > +
> > +		if (rx_data_size > comm_buf_size) {
> > +			efi_memcpy_runtime(comm_buf, virt_shared_buf, comm_buf_size);
> > +			unmap_sysmem(virt_shared_buf);
> > +			return EFI_BUFFER_TOO_SMALL;
> > +		}
> > +
> > +		efi_memcpy_runtime(comm_buf, virt_shared_buf, rx_data_size);
> > +		unmap_sysmem(virt_shared_buf);
> > +
> > +		return EFI_SUCCESS;
> > +	}
> > +	case -EINVAL:
> > +		return EFI_DEVICE_ERROR;
> > +	case -EPERM:
> > +		return EFI_INVALID_PARAMETER;
> > +	case -EACCES:
> > +		return EFI_ACCESS_DENIED;
> > +	case -EBUSY:
> > +		return EFI_OUT_OF_RESOURCES;
> > +	default:
> > +		return EFI_ACCESS_DENIED;
> > +	}
> > +}
> > +#endif
> > +
> > +/**
> > + * mm_communicate() - Adjust the communication buffer to the MM SP and send
> >   * it to OP-TEE
> >   *
> > - * @comm_buf:		locally allocted communcation buffer
> > + * @comm_buf:		locally allocated communication buffer
> >   * @dsize:		buffer size
> > + *
> > + * The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
> > + * The comm_buf format is the same for both partitions.
> > + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> > + * When using the u-boot FF-A  driver, StandAlonneMM and smm-gateway are supported.
> > + *
> >   * Return:		status code
> >   */
> > -static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> > +static efi_status_t __efi_runtime mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> >  {
> >  	efi_status_t ret;
> >  	struct efi_mm_communicate_header *mm_hdr;
> > @@ -162,9 +432,16 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> >  	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> >  	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
> >  
> > +	#if (IS_ENABLED(CONFIG_OPTEE))
> >  	ret = optee_mm_communicate(comm_buf, dsize);
> > +	#elif (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +	ret = ffa_mm_communicate(comm_buf, dsize);
> > +	#endif
> >  	if (ret != EFI_SUCCESS) {
> > -		log_err("%s failed!\n", __func__);
> > +		/* No need for showing a log here. mm_communicate failure happens
> > +		 * when getVariable() is called with data size set to 0.
> > +		 * This is not expected so no log shown.
> > +		 */
> 
> It can also fail on normal cases were the size is != 0
> 

This has been addressed on v4 patchset: https://lore.kernel.org/all/20220926101723.9965-10-abdellatif.elkhlifi@arm.com/

> >  		return ret;
> >  	}
> >  
> > @@ -258,6 +535,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
> >  		goto out;
> >  	}
> >  	*size = var_payload->size;
> > +
> > +	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
> > +			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
> > +				MM_VARIABLE_COMMUNICATE_SIZE;
> > +	#endif
> > +
> >  	/*
> >  	 * There seems to be a bug in EDK2 miscalculating the boundaries and
> >  	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> > @@ -697,7 +981,7 @@ void efi_variables_boot_exit_notify(void)
> >  		ret = EFI_NOT_FOUND;
> >  
> >  	if (ret != EFI_SUCCESS)
> > -		log_err("Unable to notify StMM for ExitBootServices\n");
> > +		log_err("Unable to notify the MM partition for ExitBootServices\n");
> >  	free(comm_buf);
> >  
> >  	/*
> > -- 
> > 2.17.1
> > 
> 
> Thanks
> /Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver
  2022-08-12  7:39                                 ` Ilias Apalodimas
@ 2022-09-26 11:11                                   ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 11:11 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, nd

On Fri, Aug 12, 2022 at 10:39:23AM +0300, Ilias Apalodimas wrote:
> Hi Abdellatif,
> 
> On Mon, 1 Aug 2022 at 20:21, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
> >
> > The Firmware Framework for Arm A-profile processors (FF-A)
> > describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World leveraging TrustZone
> > technology.
> >
> > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > querying the FF-A framework from the secure world.
> >
> > 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> > and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> >
> > In u-boot FF-A design, FF-A is considered as a discoverable bus.
> > The Secure World is considered as one entity to communicate with
> > using the FF-A bus. FF-A communication is handled by one device and
> > one instance (the bus). This FF-A driver takes care of all the
> > interactions between Normal world and Secure World.
> >
> > The driver exports its operations to be used by upper layers.
> >
> > Exported operations:
> >
> > - partition_info_get
> > - sync_send_receive
> > - rxtx_unmap
> >
> > This implementation provides an optional feature to copy the driver data
> > to EFI runtime area.
> >
> 
> [...]
> 
> > +config ARM_FFA_TRANSPORT
> > +       bool "Enable Arm Firmware Framework for Armv8-A driver"
> > +       depends on DM && ARM64
> > +       select ARM_SMCCC
> > +       select LIB_UUID
> > +       select DEVRES
> > +       help
> > +         The Firmware Framework for Arm A-profile processors (FF-A)
> > +         describes interfaces (ABIs) that standardize communication
> > +         between the Secure World and Normal World leveraging TrustZone
> > +         technology.
> > +
> > +         This driver is based on FF-A specification v1.0 and uses SMC32
> > +         calling convention.
> > +
> > +         FF-A specification:
> > +
> > +         https://developer.arm.com/documentation/den0077/a/?lang=en
> > +
> > +         In u-boot FF-A design, FF-A is considered as a discoverable bus.
> > +         The Secure World is considered as one entity to communicate with
> > +         using the FF-A bus.
> > +         FF-A communication is handled by one device and one instance (the bus).
> > +         This FF-A driver takes care of all the interactions between Normal world
> > +         and Secure World.
> > +
> > +config ARM_FFA_EFI_RUNTIME_MODE
> > +       bool "Enable EFI runtime support for FF-A data and code "
> > +       depends on ARM_FFA_TRANSPORT && EFI_LOADER
> > +       help
> > +         Allows FF-A driver data structures and code to be accessible at EFI runtime
> 
> Is there a reason we want to opt-in on that?  What prevents it from
> always being  there?

Yes, we agreed that FF-A driver needs to be independent from EFI.
This is reflected in the v4 patchset.
The intent is to be able to compile the core driver without EFI 
support. When using EFI, FF-A core driver data needs to be copied to 
the EFI runtime section so it can be accessed at runtime. For that 
specific case, CONFIG_ARM_FFA_EFI_RUNTIME_MODE has been created to
enable the feature of copying the data to the runtime section.
The code that copies the data is provided by 
drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
When EFI is needed CONFIG_ARM_FFA_EFI_RUNTIME_MODE should be turned
on. If no EFI needed the FF-A driver can still be used independently.

> 
> [...]
> 
> > +
> > +/* Endpoint ID mask (u-boot endpoint ID) */
> > +
> > +#define GET_SELF_ENDPOINT_ID_MASK              GENMASK(15, 0)
> > +#define GET_SELF_ENDPOINT_ID(x)                \
> > +                       ((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> > +
> > +#define PREP_SELF_ENDPOINT_ID_MASK             GENMASK(31, 16)
> > +#define PREP_SELF_ENDPOINT_ID(x)               \
> > +                       (FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> > +
> > +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> > +
> > +#define PREP_PART_ENDPOINT_ID_MASK             GENMASK(15, 0)
> > +#define PREP_PART_ENDPOINT_ID(x)               \
> > +                       (FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> > +
> > +/*
> > + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> > + */
> > +
> > +#define FFA_SMC(calling_convention, func_num)                          \
> > +       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),   \
> > +                          ARM_SMCCC_OWNER_STANDARD, (func_num))
> > +
> > +#define FFA_SMC_32(func_num)                           FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> > +#define FFA_SMC_64(func_num)                           FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
> > +
> > +#define FFA_VERSION                            FFA_SMC_32(0x63)
> > +#define FFA_ID_GET                             FFA_SMC_32(0x69)
> > +#define FFA_FEATURES                           FFA_SMC_32(0x64)
> > +#define FFA_PARTITION_INFO_GET                 FFA_SMC_32(0x68)
> > +#define FFA_RXTX_UNMAP                         FFA_SMC_32(0x67)
> > +#define FFA_RX_RELEASE                         FFA_SMC_32(0x65)
> > +#define FFA_RUN                                        FFA_SMC_32(0x6D)
> > +#define FFA_ERROR                              FFA_SMC_32(0x60)
> > +#define FFA_SUCCESS                            FFA_SMC_32(0x61)
> > +#define FFA_INTERRUPT                          FFA_SMC_32(0x62)
> > +#define FFA_RXTX_MAP                           FFA_SMC_64(0x66)
> > +#define FFA_MSG_SEND_DIRECT_REQ                        FFA_SMC_64(0x6F)
> > +#define FFA_MSG_SEND_DIRECT_RESP               FFA_SMC_64(0x70)
> > +
> > +/* 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);
> > +
> > +/* FF-A error codes */
> > +#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_INTERRUPTED                               (-5)
> > +#define FFA_ERR_STAT_DENIED                            (-6)
> > +#define FFA_ERR_STAT_RETRY                             (-7)
> > +#define FFA_ERR_STAT_ABORTED                           (-8)
> > +
> > +/* UUID data size */
> > +#define UUID_SIZE (16)
> 
> Please drop () on these
> 
> > +
> > +/*
> > + * union ffa_partition_uuid - Data union hosting the UUID
> > + *                                                     transmitted by FFA_PARTITION_INFO_GET
> > + * @words:     data structure giving 32-bit words access to the UUID data
> > + * @bytes:     data structure giving byte access to the UUID data
> > + *
> > + * The structure holds little-endian UUID data.
> > + */
> > +union ffa_partition_uuid {
> > +       struct __packed words {
> > +       u32 a1; /* w1 */
> > +       u32 a2; /* w2 */
> > +       u32 a3; /* w3 */
> > +       u32 a4; /* w4 */
> > +       } words;
> > +       u8 bytes[UUID_SIZE];
> > +};
> 
> is the bytes field used anywhere?

removed in v4. Please see https://lore.kernel.org/all/20220926101723.9965-5-abdellatif.elkhlifi@arm.com/

> 
> [...]
> 
> > + *
> > + * Each partition has its descriptor containing the partitions information and the UUID
> > + */
> > +struct ffa_partition_desc {
> > +       struct ffa_partition_info info;
> > +       union ffa_partition_uuid UUID;
> 
> lower case please and perhaps a better name e.g partition_uuid

Done in v4.

> 
> > +};
> > +
> > +/**
> > + * struct ffa_partitions - descriptors for all secure partitions
> > + * @count:     The number of partitions descriptors
> > + * @descs      The partitions descriptors table
> > + *
> > + * This data structure contains the partitions descriptors table
> > + */
> > +struct ffa_partitions {
> > +       u32 count;
> > +       struct ffa_partition_desc *descs; /* virtual address */
> > +};
> > +
> > +/**
> > + * struct ffa_prvdata - the driver private data structure
> > + *
> > + * @dev:       The arm_ffa device under u-boot driver model
> > + * @ffa_ops:   The driver operations structure
> > + * @fwk_version:       FF-A framework version
> > + * @id:        u-boot endpoint ID
> > + * @partitions:        The partitions descriptors structure
> > + * @pair:      The RX/TX buffers pair
> > + * @invoke_ffa_fn:     The function executing the FF-A function
> > + * @features:  Table of the FF-A functions having features
> > + *
> > + * The driver data structure hosting all resident data.
> > + */
> > +struct ffa_prvdata {
> > +       struct udevice *dev;
> > +       struct ffa_bus_ops ffa_ops;
> > +       u32 fwk_version;
> > +       u16 id;
> > +       struct ffa_partitions partitions;
> > +       struct ffa_rxtxpair pair;
> > +       invoke_ffa_fn_t invoke_ffa_fn;
> > +       struct ffa_features_desc features[FFA_FEATURE_DESC_CNT];
> > +};
> > +
> > +/**
> > + * ffa_device_get - create, bind and probe the arm_ffa device
> > + */
> > +int ffa_device_get(void);
> > +
> > +/**
> > + * ffa_bus_prvdata_get - bus driver private data getter
> > + */
> > +struct ffa_prvdata **ffa_bus_prvdata_get(void);
> > +
> > +#endif
> > diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c
> > new file mode 100644
> > index 0000000000..40d140fc3e
> > --- /dev/null
> > +++ b/drivers/arm-ffa/core.c
> > @@ -0,0 +1,1338 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include "arm_ffa_prv.h"
> > +#include <asm/global_data.h>
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <dm/device-internal.h>
> > +#include <dm/devres.h>
> > +#include <dm/root.h>
> > +#include <linux/errno.h>
> > +#include <linux/sizes.h>
> > +#include <log.h>
> > +#include <malloc.h>
> > +#include <string.h>
> > +#include <uuid.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/**
> > + * The device private data structure containing all the resident
> > + * data read from secure world
> > + */
> > +__ffa_runtime_data struct ffa_prvdata *ffa_priv_data;
> 
> I think it's better if we just keep this as efi_runtime, especially
> since the rest of the declarations you use are marked as efi_*

In v4 the core driver is no longer dependent on EFI. The intent is to 
be able to compile it without EFI support. So, we can't use
__efi_runtime* in the FFA driver when EFI is off.

__ffa_runtime* keywords are created in include/arm_ffa.h

Based on wether CONFIG_ARM_FFA_EFI_RUNTIME_MODE is on or off
__ffa_runtime* are set to __efi_runtime* or kept empty if the config 
is off.

> 
> [...]
> 
> > +
> > +/**
> > + * ffa_device_get - create, bind and probe the arm_ffa device
> > + *
> > + * This boot time function makes sure the arm_ffa device is
> > + * created, bound to this driver, probed and ready to use.
> > + * Arm FF-A transport is implemented through a single u-boot
> > + * device managing the FF-A bus (arm_ffa).
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +int ffa_device_get(void)
> > +{
> > +       int ret;
> > +       struct udevice *dev = NULL;
> > +
> > +       if (ffa_priv_data && ffa_priv_data->dev)
> > +               return FFA_ERR_STAT_SUCCESS;
> > +
> > +       ret = device_bind(dm_root(),
> > +                         DM_DRIVER_GET(arm_ffa),
> > +                         FFA_DRV_NAME,
> > +                         NULL,
> > +                         ofnode_null(),
> > +                         &dev);
> > +       if (ret)
> > +               return ret;
> > +
> > +       /* The FF-A bus discovery succeeds when probing is successful */
> > +       ret = device_probe(dev);
> > +       if (ret) {
> > +               ffa_err("arm_ffa device probing failed");
> > +               ffa_remove_device(dev);
> > +               return ret;
> > +       }
> > +
> > +       return FFA_ERR_STAT_SUCCESS;
> 
> The return values in most of the functions are confusing.  I think you
> should just get rid of FFA_ERR_STAT_SUCCESS and just return 0

Error handling and panics have been addressed in v4 patchset.
As stated in the v3 cover letter, error handling and panics will
be addressed in v4.

Please refer to this patch for the latest work:
https://lore.kernel.org/all/20220926101723.9965-5-abdellatif.elkhlifi@arm.com/

> 
> [...]
> 
> > +
> > +       if (!ffa_priv_data->invoke_ffa_fn)
> > +               panic("[FFA] no private data found\n");
> 
> Get rid of all the panicking please.  We've discussed this on a
> previous email.  Isn't an error message enough?

Error handling and panics have been addressed in v4 patchset.
As stated in the v3 cover letter, error handling and panics will 
be addressed in v4.

Please refer to this patch for the latest work: 
https://lore.kernel.org/all/20220926101723.9965-5-abdellatif.elkhlifi@arm.com/

> 
> [...]
> 
> > + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> > + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> > + *                       buffers
> > + *
> > + * This is the boot time function that implements FFA_RXTX_MAP FF-A function
> > + * to map the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_map_rxtx_buffers(size_t buf_4k_pages)
> > +{
> > +       int ret;
> > +       ffa_value_t res = {0};
> > +
> > +       if (!ffa_priv_data->invoke_ffa_fn)
> > +               panic("[FFA] no private data found\n");
> > +
> > +       ret = ffa_alloc_rxtx_buffers(buf_4k_pages);
> > +       if (ret != FFA_ERR_STAT_SUCCESS)
> > +               return ret;
> > +
> > +       /*
> > +        * we need to pass the physical addresses of the RX/TX buffers
> > +        * in u-boot physical/virtual mapping is 1:1
> > +        *no need to convert from virtual to physical
> > +        */
> > +
> > +       ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +                       .a0 = FFA_RXTX_MAP,
> > +                       .a1 = ffa_priv_data->pair.txbuf,
> > +                       .a2 = ffa_priv_data->pair.rxbuf,
> > +                       .a3 = buf_4k_pages,
> > +                       .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> > +                       }, &res);
> > +
> > +       switch (res.a0) {
> > +       case FFA_ERROR:
> > +       {
> 
> There are comments in v2 that are ignored throughout the patchset.
> Please check the remarks in v2 before sending a new patchset

Error handling and panics have been addressed in v4 patchset.
As stated in the v3 cover letter, error handling and panics will
be addressed in v4.

Please refer to this patch for the latest work:
https://lore.kernel.org/all/20220926101723.9965-5-abdellatif.elkhlifi@arm.com/

> 
> 
> > +               switch (((int)res.a2)) {
> > +               case FFA_ERR_STAT_INVALID_PARAMETERS:
> > +                       ffa_err("One or more fields in input parameters is incorrectly encoded");
> > +                       ret = -EPERM;
> > +                       break;
> > +               case FFA_ERR_STAT_NO_MEMORY:
> > +                       ffa_err("Not enough memory");
> > +                       ret = -ENOMEM;
> > +                       break;
> > +               case FFA_ERR_STAT_DENIED:
> > +                       ffa_err("Buffer pair already registered");
> > +                       ret = -EACCES;
> > +                       break;
> > +               case FFA_ERR_STAT_NOT_SUPPORTED:
> > +                       ffa_err("This function is not implemented at this FF-A instance");
> > +                       ret = -EOPNOTSUPP;
> > +                       break;
> > +               default:
> > +                       ffa_err("Undefined error (%d)",
> > +                               ((int)res.a2));
> > +                       ret = -EINVAL;
> > +               }
> > +               break;
> > +       }
> > +       case FFA_SUCCESS:
> > +               ffa_info("RX/TX buffers mapped");
> > +               return FFA_ERR_STAT_SUCCESS;
> > +       default:
> > +               ffa_err("Undefined response function (0x%lx)",
> > +                       res.a0);
> > +               ret = -EINVAL;
> > +       }
> > +
> > +       ffa_free_rxtx_buffers();
> > +
> > +       return ret;
> > +}
> > +
> > +/**
> [...]
> 
> Regards
> /Ilias
> 
> 
> > +
> > +/**
> > + * Declaring the arm_ffa driver under UCLASS_FFA
> > + */
> > +
> > +U_BOOT_DRIVER(arm_ffa) = {
> > +       .name           = FFA_DRV_NAME,
> > +       .id             = UCLASS_FFA,
> > +       .probe          = ffa_probe,
> > +};
> > diff --git a/drivers/arm-ffa/efi_ffa_runtime_data_mgr.c b/drivers/arm-ffa/efi_ffa_runtime_data_mgr.c
> > new file mode 100644
> > index 0000000000..942601a7ba
> > --- /dev/null
> > +++ b/drivers/arm-ffa/efi_ffa_runtime_data_mgr.c
> > @@ -0,0 +1,94 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include "arm_ffa_prv.h"
> > +
> > +/**
> > + * ffa_copy_runtime_data - copy the private data structure  to the runtime area
> > + *
> > + * This boot time function copies the arm_ffa driver data structures including
> > + *  partitions data to the EFI runtime data section.
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +efi_status_t ffa_copy_runtime_data(void)
> > +{
> > +       efi_status_t efi_ret;
> > +       efi_uintn_t prvdata_pages;
> > +       efi_uintn_t descs_pages;
> > +       struct ffa_prvdata **prvdata = NULL; /* Pointer to the current structure */
> > +       struct ffa_prvdata *runtime_prvdata = NULL; /* Pointer to the structure runtime copy */
> > +       u64 runtime_descs = 0;
> > +
> > +       prvdata = ffa_bus_prvdata_get();
> > +
> > +       printf("INFO: EFI: FFA: prv data area at 0x%llx\n", (u64)prvdata);
> > +
> > +       /* allocate private data runtime area */
> > +
> > +       prvdata_pages = efi_size_in_pages(sizeof(struct ffa_prvdata));
> > +       efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> > +                                    EFI_RUNTIME_SERVICES_DATA,
> > +                                    prvdata_pages,
> > +                                    (u64 *)&runtime_prvdata);
> > +
> > +       if (efi_ret != EFI_SUCCESS) {
> > +               printf("ERROR: EFI: FFA: allocating runtime data (err: 0x%lx, addr 0x%llx)\n",
> > +                      efi_ret, (u64)runtime_prvdata);
> > +
> > +               return efi_ret;
> > +       }
> > +
> > +       printf("INFO: EFI: FFA: runtime data area at 0x%llx\n", (u64)runtime_prvdata);
> > +
> > +       if (!runtime_prvdata)
> > +               return EFI_INVALID_PARAMETER;
> > +
> > +       /* allocate the partition data runtime area */
> > +
> > +       descs_pages = efi_size_in_pages((*prvdata)->partitions.count *
> > +                                       sizeof(struct ffa_partition_desc));
> > +       efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> > +                                    EFI_RUNTIME_SERVICES_DATA,
> > +                                    descs_pages,
> > +                                    &runtime_descs);
> > +
> > +       if (efi_ret != EFI_SUCCESS) {
> > +               printf("ERROR: EFI: FFA: allocating runtime SPs data (err: 0x%lx, addr 0x%llx)\n",
> > +                      efi_ret, runtime_descs);
> > +
> > +               efi_free_pages((u64)runtime_prvdata, prvdata_pages);
> > +
> > +               return efi_ret;
> > +       }
> > +
> > +       printf("INFO: EFI: FFA: SPs runtime area at 0x%llx\n", (u64)runtime_descs);
> > +
> > +       if (!runtime_descs)
> > +               return EFI_INVALID_PARAMETER;
> > +
> > +       *runtime_prvdata = **prvdata;
> > +
> > +       runtime_prvdata->dev = NULL;
> > +       runtime_prvdata->ffa_ops.partition_info_get = NULL;
> > +       runtime_prvdata->ffa_ops.rxtx_unmap = NULL;
> > +       runtime_prvdata->partitions.descs = (struct ffa_partition_desc *)runtime_descs;
> > +       runtime_prvdata->pair.rxbuf = 0;
> > +       runtime_prvdata->pair.txbuf = 0;
> > +
> > +       /*
> > +        * Update the private data structure pointer in the driver
> > +        * no need to free the old structure. devm takes care of that
> > +        */
> > +       *prvdata = runtime_prvdata;
> > +
> > +       printf("INFO: EFI: FFA: runtime prv data now at 0x%llx , SPs count %d\n",
> > +              (u64)*prvdata, (*prvdata)->partitions.count);
> > +
> > +       return FFA_ERR_STAT_SUCCESS;
> > +}
> > diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> > new file mode 100644
> > index 0000000000..ee9ce2d99d
> > --- /dev/null
> > +++ b/include/arm_ffa.h
> > @@ -0,0 +1,132 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_H
> > +#define __ARM_FFA_H
> > +
> > +#include <linux/printk.h>
> > +
> > +/*
> > + * This header is public. It can be used by clients to access
> > + * data structures and definitions they need
> > + */
> > +
> > +/*
> > + * Macros for displaying logs
> > + */
> > +
> > +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +
> > +/*
> > + * The driver operations success error code
> > + */
> > +#define FFA_ERR_STAT_SUCCESS                           (0)
> > +
> > +/*
> > + * struct ffa_partition_info - Partition information descriptor
> > + * @id:        Partition ID
> > + * @exec_ctxt: Execution context count
> > + * @properties:        Partition properties
> > + *
> > + * Data structure containing information about partitions instantiated in the system
> > + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> > + */
> > +struct  __packed ffa_partition_info {
> > +       u16 id;
> > +       u16 exec_ctxt;
> > +/* partition supports receipt of direct requests */
> > +#define FFA_PARTITION_DIRECT_RECV      BIT(0)
> > +/* partition can send direct requests. */
> > +#define FFA_PARTITION_DIRECT_SEND      BIT(1)
> > +/* partition can send and receive indirect messages. */
> > +#define FFA_PARTITION_INDIRECT_MSG     BIT(2)
> > +       u32 properties;
> > +};
> > +
> > +/*
> > + * struct ffa_send_direct_data - Data structure hosting the data
> > + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * @data0-4:   Data read/written from/to x3-x7 registers
> > + *
> > + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> > + * or read from FFA_MSG_SEND_DIRECT_RESP
> > + */
> > +
> > +/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
> > +struct __packed ffa_send_direct_data {
> > +       unsigned long data0; /* w3/x3 */
> > +       unsigned long data1; /* w4/x4 */
> > +       unsigned long data2; /* w5/x5 */
> > +       unsigned long data3; /* w6/x6 */
> > +       unsigned long data4; /* w7/x7 */
> > +};
> > +
> > +#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
> > +
> > +#include <efi_loader.h>
> > +
> > +/*
> > + *  __ffa_runtime - controls whether functions are
> > + * available after calling the EFI ExitBootServices service.
> > + * Functions tagged with these keywords are resident (available at boot time and
> > + * at runtime)
> > + */
> > +
> > +#define __ffa_runtime_data __efi_runtime_data
> > +#define __ffa_runtime __efi_runtime
> > +
> > +#else
> > +
> > +/*
> > + *  The FF-A driver is independent from EFI
> > + */
> > +
> > +#define __ffa_runtime_data
> > +#define __ffa_runtime
> > +
> > +#endif
> > +
> > +/**
> > + * struct ffa_bus_ops - The driver operations structure
> > + * @partition_info_get:        callback for the FFA_PARTITION_INFO_GET
> > + * @sync_send_receive: callback for the FFA_MSG_SEND_DIRECT_REQ
> > + * @rxtx_unmap:        callback for the FFA_RXTX_UNMAP
> > + *
> > + * The data structure providing all the operations supported by the driver.
> > + * This structure is EFI runtime resident.
> > + */
> > +struct ffa_bus_ops {
> > +       int (*partition_info_get)(const char *uuid_str,
> > +                                 u32 *parts_size, struct ffa_partition_info *buffer);
> > +       int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg);
> > +       int (*rxtx_unmap)(void);
> > +};
> > +
> > +/**
> > + * The device driver and the Uclass driver public functions
> > + */
> > +
> > +/**
> > + * ffa_bus_ops_get - driver operations getter
> > + */
> > +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
> > + */
> > +int ffa_bus_discover(void);
> > +
> > +#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
> > +
> > +/**
> > + * ffa_copy_runtime_data - copy the private data structure and the SPs data to the runtime area
> > + */
> > +efi_status_t ffa_copy_runtime_data(void);
> > +
> > +#endif
> > +
> > +#endif
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index a432e43871..6eebbe9c7d 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -55,6 +55,7 @@ enum uclass_id {
> >         UCLASS_EFI_MEDIA,       /* Devices provided by UEFI firmware */
> >         UCLASS_ETH,             /* Ethernet device */
> >         UCLASS_ETH_PHY,         /* Ethernet PHY device */
> > +       UCLASS_FFA,             /* Arm Firmware Framework for Armv8-A */
> >         UCLASS_FIRMWARE,        /* Firmware */
> >         UCLASS_FUZZING_ENGINE,  /* Fuzzing engine */
> >         UCLASS_FS_FIRMWARE_LOADER,              /* Generic loader */
> > diff --git a/include/uuid.h b/include/uuid.h
> > index 4a4883d3b5..789f8e0f15 100644
> > --- a/include/uuid.h
> > +++ b/include/uuid.h
> > @@ -44,4 +44,12 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
> >  const char *uuid_guid_get_str(const unsigned char *guid_bin);
> >  void gen_rand_uuid(unsigned char *uuid_bin);
> >  void gen_rand_uuid_str(char *uuid_str, int str_format);
> > +
> > +#ifdef CONFIG_ARM_FFA_TRANSPORT
> > +/**
> > + * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
> > + */
> > +int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin);
> > +#endif
> > +
> >  #endif
> > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> > index 4da64b5d29..e02bb445f5 100644
> > --- a/lib/efi_loader/efi_boottime.c
> > +++ b/lib/efi_loader/efi_boottime.c
> > @@ -23,6 +23,10 @@
> >  #include <asm/setjmp.h>
> >  #include <linux/libfdt_env.h>
> >
> > +#if defined(CONFIG_ARM_FFA_TRANSPORT)
> > +#include <arm_ffa.h>
> > +#endif
> > +
> >  DECLARE_GLOBAL_DATA_PTR;
> >
> >  /* Task priority level */
> > @@ -2113,6 +2117,10 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
> >         struct efi_event *evt, *next_event;
> >         efi_status_t ret = EFI_SUCCESS;
> >
> > +#if defined(CONFIG_ARM_FFA_TRANSPORT)
> > +       int ffa_ret;
> > +#endif
> > +
> >         EFI_ENTRY("%p, %zx", image_handle, map_key);
> >
> >         /* Check that the caller has read the current memory map */
> > @@ -2173,6 +2181,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
> >                 dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
> >         }
> >
> > +#if defined(CONFIG_ARM_FFA_TRANSPORT)
> > +       /* unmap FF-A RX/TX buffers */
> > +       ffa_ret = ffa_bus_ops_get()->rxtx_unmap();
> > +       if (ffa_ret)
> > +               debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n");
> > +       else
> > +               debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
> > +#endif
> > +
> >         /* Patch out unsupported runtime function */
> >         efi_runtime_detach();
> >
> > diff --git a/lib/uuid.c b/lib/uuid.c
> > index 284f8113ff..50b3e61d59 100644
> > --- a/lib/uuid.c
> > +++ b/lib/uuid.c
> > @@ -1,6 +1,7 @@
> >  // SPDX-License-Identifier: GPL-2.0+
> >  /*
> >   * Copyright 2011 Calxeda, Inc.
> > + * Copyright 2022 ARM Limited
> >   */
> >
> >  #include <common.h>
> > @@ -342,6 +343,70 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
> >         return 0;
> >  }
> >
> > +#ifdef CONFIG_ARM_FFA_TRANSPORT
> > +/**
> > + * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
> > + * @uuid_str:  UUID string in big endian format (36 bytes wide + '/0')
> > + * @uuid_bin:  preallocated 16 bytes UUID buffer in little endian format
> > + *
> > + * UUID string is 36 characters (36 bytes):
> > + *
> > + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
> > + * be               be      be       be      be
> > + *
> > + * where x is a hexadecimal character. Fields are separated by '-'s.
> > + * When converting to a binary UUID, these endianness rules apply:
> > + *     be: means the field in the string is considered a big endian hex number
> > + *        and should be converted to little endian binary format
> > + *
> > + * Return:
> > + *
> > + *    uuid_bin filled with little endian UUID data
> > + *    On success 0 is returned. Otherwise, failure code.
> > + */
> > +int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin)
> > +{
> > +       u16 tmp16 = 0;
> > +       u32 tmp32 = 0;
> > +       u64 tmp64 = 0;
> > +
> > +       if (!uuid_str_valid(uuid_str) || !uuid_bin)
> > +               return -EINVAL;
> > +
> > +       /*
> > +        * reverse bytes from big to little endian
> > +        */
> > +       tmp32 = simple_strtoul(uuid_str, NULL, 16);
> > +       memcpy(uuid_bin, &tmp32, 4);
> > +
> > +       /*
> > +        * reverse bytes from big to little endian
> > +        */
> > +       tmp16 = simple_strtoul(uuid_str + 9, NULL, 16);
> > +       memcpy(uuid_bin + 4, &tmp16, 2);
> > +
> > +       /*
> > +        * reverse bytes from big to little endian
> > +        */
> > +       tmp16 = simple_strtoul(uuid_str + 14, NULL, 16);
> > +       memcpy(uuid_bin + 6, &tmp16, 2);
> > +
> > +       /*
> > +        * reverse bytes from big to little endian
> > +        */
> > +       tmp16 = simple_strtoul(uuid_str + 19, NULL, 16);
> > +       memcpy(uuid_bin + 8, &tmp16, 2);
> > +
> > +       /*
> > +        * reverse bytes from big to little endian
> > +        */
> > +       tmp64 = simple_strtoull(uuid_str + 24, NULL, 16);
> > +       memcpy(uuid_bin + 10, (char *)&tmp64, 6);
> > +
> > +       return 0;
> > +}
> > +#endif
> > +
> >  /*
> >   * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
> >   *
> > --
> > 2.17.1
> >

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v2 1/6] arm_ffa: introduce Arm FF-A low-level driver
  2022-05-13 14:40                       ` Jens Wiklander
@ 2022-09-26 11:30                         ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 11:30 UTC (permalink / raw)
  To: Jens Wiklander; +Cc: u-boot, nd

On Fri, May 13, 2022 at 04:40:36PM +0200, Jens Wiklander wrote:
> On Fri, Apr 15, 2022 at 01:27:58PM +0100, abdellatif.elkhlifi@arm.com wrote:
> > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > 
> > Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
> > 
> > The Firmware Framework for Arm A-profile processors (FF-A)
> > describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World leveraging TrustZone
> > technology. This driver uses SMC32 calling convention.
> 
> How come only the SMC32 calling convention is used? What if you need
> 64-bit pointers for some reason (RXTX_MAP comes to mind) ? Doing the
> 64-bit calling convention at the same time can't be much more work.

Thanks for the feedback. SMC64 support has been added in v3 patchset. 
Please refer to the latest work provided by v4:
https://lore.kernel.org/all/20220926101723.9965-2-abdellatif.elkhlifi@arm.com/

> 
> > 
> > In u-boot FF-A design, FF-A is considered as a discoverable bus.
> > The Secure World is considered as one entity to communicate with
> > using the FF-A bus. FF-A communication is handled by one device and
> > one instance (the bus). This FF-A driver takes care of all the
> > interactions between Normal world and Secure World.
> > 
> > The driver provides helper FF-A interfaces for user layers.
> > These helper functions allow clients to pass data and select the
> > FF-A function to use for the communication with secure world.
> > 
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > ---
> >  MAINTAINERS                      |    8 +
> >  arch/arm/cpu/armv8/smccc-call.S  |   27 +
> >  arch/arm/lib/asm-offsets.c       |    6 +
> >  common/board_r.c                 |    7 +
> >  drivers/Kconfig                  |    2 +
> >  drivers/Makefile                 |    1 +
> >  drivers/arm-ffa/Kconfig          |   27 +
> >  drivers/arm-ffa/Makefile         |    6 +
> >  drivers/arm-ffa/arm-ffa-uclass.c |   64 ++
> >  drivers/arm-ffa/arm_ffa_prv.h    |  193 +++++
> >  drivers/arm-ffa/core.c           | 1349 ++++++++++++++++++++++++++++++
> >  include/arm_ffa.h                |  190 +++++
> >  include/arm_ffa_helper.h         |   45 +
> >  include/dm/uclass-id.h           |    1 +
> >  include/linux/arm-smccc.h        |   28 +-
> >  lib/Kconfig                      |    1 +
> >  lib/Makefile                     |    1 +
> >  lib/arm-ffa/Kconfig              |    6 +
> >  lib/arm-ffa/Makefile             |    8 +
> >  lib/arm-ffa/arm_ffa_helper.c     |  188 +++++
> >  lib/efi_loader/efi_boottime.c    |   17 +
> >  21 files changed, 2174 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/arm-ffa/Kconfig
> >  create mode 100644 drivers/arm-ffa/Makefile
> >  create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
> >  create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
> >  create mode 100644 drivers/arm-ffa/core.c
> >  create mode 100644 include/arm_ffa.h
> >  create mode 100644 include/arm_ffa_helper.h
> >  create mode 100644 lib/arm-ffa/Kconfig
> >  create mode 100644 lib/arm-ffa/Makefile
> >  create mode 100644 lib/arm-ffa/arm_ffa_helper.c
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index aca97cd2a3..efa17206b8 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -232,6 +232,14 @@ F:	board/CZ.NIC/
> >  F:	configs/turris_*_defconfig
> >  F:	include/configs/turris_*.h
> >  
> > +ARM FF-A
> > +M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > +S:	Maintained
> > +F:	drivers/arm-ffa/
> > +F:	include/arm_ffa.h
> > +F:	include/arm_ffa_helper.h
> > +F:	lib/arm-ffa/
> > +
> >  ARM FREESCALE IMX
> >  M:	Stefano Babic <sbabic@denx.de>
> >  M:	Fabio Estevam <festevam@gmail.com>
> > diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
> > index dc92b28777..9a6aebf194 100644
> > --- a/arch/arm/cpu/armv8/smccc-call.S
> > +++ b/arch/arm/cpu/armv8/smccc-call.S
> > @@ -1,6 +1,8 @@
> >  /* SPDX-License-Identifier: GPL-2.0 */
> >  /*
> >   * Copyright (c) 2015, Linaro Limited
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  #include <linux/linkage.h>
> >  #include <linux/arm-smccc.h>
> > @@ -45,3 +47,28 @@ ENDPROC(__arm_smccc_smc)
> >  ENTRY(__arm_smccc_hvc)
> >  	SMCCC	hvc
> >  ENDPROC(__arm_smccc_hvc)
> > +
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +
> > +	.macro FFASMCCC instr
> > +	.cfi_startproc
> > +	\instr	#0
> > +	ldr	x9, [sp]
> > +	stp	x0, x1, [x9, #ARM_SMCCC_RES_X0_OFFS]
> > +	stp	x2, x3, [x9, #ARM_SMCCC_RES_X2_OFFS]
> > +	stp	x4, x5, [x9, #ARM_SMCCC_RES_X4_OFFS]
> > +	stp	x6, x7, [x9, #ARM_SMCCC_RES_X6_OFFS]
> > +	ret
> > +	.cfi_endproc
> > +	.endm
> > +
> > +/*
> > + * void arm_ffa_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
> > + *		  unsigned long a3, unsigned long a4, unsigned long a5,
> > + *		  unsigned long a6, unsigned long a7, struct arm_smccc_res *res)
> > + */
> > +ENTRY(__arm_ffa_smccc_smc)
> > +	FFASMCCC	smc
> > +ENDPROC(__arm_ffa_smccc_smc)
> > +
> > +#endif
> > diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
> > index 22fd541f9a..02a4a42fe6 100644
> > --- a/arch/arm/lib/asm-offsets.c
> > +++ b/arch/arm/lib/asm-offsets.c
> > @@ -9,6 +9,8 @@
> >   * generate asm statements containing #defines,
> >   * compile this file to assembler, and then extract the
> >   * #defines from the assembly-language output.
> > + *
> > + * (C) Copyright 2022 ARM Limited
> >   */
> >  
> >  #include <common.h>
> > @@ -115,6 +117,10 @@ int main(void)
> >  #ifdef CONFIG_ARM_SMCCC
> >  	DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
> >  	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +	DEFINE(ARM_SMCCC_RES_X4_OFFS, offsetof(struct arm_smccc_res, a4));
> > +	DEFINE(ARM_SMCCC_RES_X6_OFFS, offsetof(struct arm_smccc_res, a6));
> > +#endif
> >  	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
> >  	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
> >  #endif
> > diff --git a/common/board_r.c b/common/board_r.c
> > index b92c1bb0be..bb5f1d0aa6 100644
> > --- a/common/board_r.c
> > +++ b/common/board_r.c
> > @@ -62,6 +62,10 @@
> >  #include <asm-generic/gpio.h>
> >  #include <efi_loader.h>
> >  
> > +#ifdef CONFIG_ARM_FFA_TRANSPORT
> > +#include <arm_ffa_helper.h>
> > +#endif
> > +
> >  DECLARE_GLOBAL_DATA_PTR;
> >  
> >  ulong monitor_flash_len;
> > @@ -771,6 +775,9 @@ static init_fnc_t init_sequence_r[] = {
> >  	INIT_FUNC_WATCHDOG_RESET
> >  	initr_net,
> >  #endif
> > +#ifdef CONFIG_ARM_FFA_TRANSPORT
> > +	ffa_helper_bus_discover,
> > +#endif
> >  #ifdef CONFIG_POST
> >  	initr_post,
> >  #endif
> > diff --git a/drivers/Kconfig b/drivers/Kconfig
> > index b26ca8cf70..e83c23789d 100644
> > --- a/drivers/Kconfig
> > +++ b/drivers/Kconfig
> > @@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
> >  
> >  source "drivers/adc/Kconfig"
> >  
> > +source "drivers/arm-ffa/Kconfig"
> > +
> >  source "drivers/ata/Kconfig"
> >  
> >  source "drivers/axi/Kconfig"
> > diff --git a/drivers/Makefile b/drivers/Makefile
> > index 4e7cf28440..6671d2a604 100644
> > --- a/drivers/Makefile
> > +++ b/drivers/Makefile
> > @@ -107,6 +107,7 @@ obj-y += iommu/
> >  obj-y += smem/
> >  obj-y += thermal/
> >  obj-$(CONFIG_TEE) += tee/
> > +obj-$(CONFIG_ARM_FFA_TRANSPORT) += arm-ffa/
> >  obj-y += axi/
> >  obj-y += ufs/
> >  obj-$(CONFIG_W1) += w1/
> > diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
> > new file mode 100644
> > index 0000000000..23815534c4
> > --- /dev/null
> > +++ b/drivers/arm-ffa/Kconfig
> > @@ -0,0 +1,27 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +config ARM_FFA_TRANSPORT
> > +	bool "Enable Arm Firmware Framework for Armv8-A driver"
> > +	depends on DM && ARM64
> > +	select ARM_SMCCC if ARM64
> > +	select LIB_UUID
> > +	select ARM_FFA_TRANSPORT_HELPERS
> > +	help
> > +	  The Firmware Framework for Arm A-profile processors (FF-A)
> > +	  describes interfaces (ABIs) that standardize communication
> > +	  between the Secure World and Normal World leveraging TrustZone
> > +	  technology.
> > +
> > +	  This driver is based on FF-A specification v1.0 and uses SMC32
> > +	  calling convention.
> > +
> > +	  FF-A specification:
> > +
> > +	  https://developer.arm.com/documentation/den0077/a/?lang=en
> > +
> > +	  In u-boot FF-A design, FF-A is considered as a discoverable bus.
> > +	  The Secure World is considered as one entity to communicate with
> > +	  using the FF-A bus.
> > +	  FF-A communication is handled by one device and one instance (the bus).
> > +	  This FF-A driver takes care of all the interactions between Normal world
> > +	  and Secure World.
> > diff --git a/drivers/arm-ffa/Makefile b/drivers/arm-ffa/Makefile
> > new file mode 100644
> > index 0000000000..7bc9a336a9
> > --- /dev/null
> > +++ b/drivers/arm-ffa/Makefile
> > @@ -0,0 +1,6 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +#
> > +# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > +#
> > +
> > +obj-y += arm-ffa-uclass.o core.o
> > diff --git a/drivers/arm-ffa/arm-ffa-uclass.c b/drivers/arm-ffa/arm-ffa-uclass.c
> > new file mode 100644
> > index 0000000000..2439f87586
> > --- /dev/null
> > +++ b/drivers/arm-ffa/arm-ffa-uclass.c
> > @@ -0,0 +1,64 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <arm_ffa.h>
> > +#include <errno.h>
> > +#include <log.h>
> > +#include <asm/global_data.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +UCLASS_DRIVER(ffa) = {
> > +	.name		= "ffa",
> > +	.id		= UCLASS_FFA,
> > +};
> > +
> > +/**
> > + * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher
> > + * @func_id:	The FF-A function to be used
> > + * @func_data:  Pointer to the FF-A function arguments
> > + *				container structure. This also includes
> > + *				pointers to the returned data needed by
> > + *				clients.
> > + *
> > + * This runtime function passes the FF-A function ID and its arguments to
> > + * the FF-A driver dispatcher.
> > + * This function is called by the FF-A helper functions.
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +int __ffa_runtime ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *func_data)
> > +{
> > +	if (!ffa_device_get_ops()->invoke_func)
> > +		return -EINVAL;
> > +
> > +	return ffa_device_get_ops()->invoke_func(func_id, func_data);
> > +}
> > +
> > +/**
> > + * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
> > + *
> > + * This boot time function makes sure the FF-A bus is discoverable.
> > + * Then, the arm_ffa device is probed and ready to use.
> > + * This function is called automatically at initcalls
> > + * level (after u-boot relocation).
> > + *
> > + * Arm FF-A transport is implemented through arm_ffa u-boot device managing the FF-A
> > + * communication.
> > + * All FF-A clients should use the arm_ffa device to use the FF-A transport.
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +int ffa_bus_discover(void)
> > +{
> > +	return ffa_get_device();
> > +}
> > diff --git a/drivers/arm-ffa/arm_ffa_prv.h b/drivers/arm-ffa/arm_ffa_prv.h
> > new file mode 100644
> > index 0000000000..44f258addb
> > --- /dev/null
> > +++ b/drivers/arm-ffa/arm_ffa_prv.h
> > @@ -0,0 +1,193 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_PRV_H
> > +#define __ARM_FFA_PRV_H
> > +
> > +#include <arm_ffa.h>
> > +#include <linux/bitfield.h>
> > +#include <linux/bitops.h>
> > +#include <dm/read.h>
> > +
> > +/*
> > + * This header is private. It is exclusively used by the FF-A driver
> > + */
> > +
> > +/* FF-A core driver name */
> > +#define FFA_DRV_NAME "arm_ffa"
> > +
> > +/* FF-A driver version definitions */
> > +
> > +#define MAJOR_VERSION_MASK		GENMASK(30, 16)
> > +#define MINOR_VERSION_MASK		GENMASK(15, 0)
> > +#define GET_FFA_MAJOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> > +#define GET_FFA_MINOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> > +#define PACK_VERSION_INFO(major, minor)			\
> > +	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
> > +	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> > +
> > +#define FFA_MAJOR_VERSION		(1)
> > +#define FFA_MINOR_VERSION		(0)
> > +#define FFA_VERSION_1_0		\
> > +			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> > +
> > +/* Endpoint ID mask (u-boot endpoint ID) */
> > +
> > +#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define GET_SELF_ENDPOINT_ID(x)		\
> > +			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> > +
> > +#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
> > +#define PREP_SELF_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> > +
> > +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> > +
> > +#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define PREP_PART_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> > +
> > +/* The FF-A SMC function prototype definition */
> > +
> > +typedef void (*invoke_ffa_fn_t)(unsigned long a0, unsigned long a1,
> > +			unsigned long a2, unsigned long a3, unsigned long a4,
> > +			unsigned long a5, unsigned long a6, unsigned long a7,
> > +			struct arm_smccc_res *res);
> > +
> > +/**
> > + * enum ffa_conduit - Arm FF-A conduits supported by the Arm FF-A driver
> > + * Currently only SMC32 is supported.
> > + */
> > +enum ffa_conduit {
> > +	FFA_CONDUIT_SMC = 0,
> > +};
> 
> Why is this enum needed?

Removed in v4. Please check https://lore.kernel.org/all/20220926101723.9965-5-abdellatif.elkhlifi@arm.com/

> 
> > +
> > +/**
> > + * FFA_DECLARE_ARGS - FF-A functions local variables
> > + * @a0-a7:	local variables used to set registers x0-x7
> > + * @res:	the structure hosting the FF-A function return data
> > + *
> > + * A helper macro for declaring local variables for the FF-A functions  arguments.
> > + * The x0-x7 registers are used to exchange data with the secure world.
> > + * But, only the bottom 32-bit of thes registers contains the data.
> > + */
> > +#define FFA_DECLARE_ARGS \
> > +	unsigned long a0 = 0; \
> > +	unsigned long a1 = 0; \
> > +	unsigned long a2 = 0; \
> > +	unsigned long a3 = 0; \
> > +	unsigned long a4 = 0; \
> > +	unsigned long a5 = 0; \
> > +	unsigned long a6 = 0; \
> > +	unsigned long a7 = 0; \
> > +	struct arm_smccc_res res = {0}
> > +
> > +/* FF-A error codes */
> > +#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_INTERRUPTED				(-5)
> > +#define FFA_ERR_STAT_DENIED				(-6)
> > +#define FFA_ERR_STAT_RETRY				(-7)
> > +#define FFA_ERR_STAT_ABORTED				(-8)
> > +
> > +/**
> > + * struct ffa_features_desc - FF-A functions features
> > + * @func_id:	FF-A function
> > + * @field1:	features read from register w2
> > + * @field2:	features read from register w3
> > + *
> > + * Data structure describing the features of the  FF-A functions queried by
> > + * FFA_FEATURES
> > + */
> > +struct ffa_features_desc {
> > +	u32 func_id;
> > +	u32 field1;
> > +	u32 field2;
> > +};
> > +
> > +/**
> > + * enum ffa_rxtx_buf_sizes - minimum sizes supported
> > + * for the RX/TX buffers
> > + */
> > +enum ffa_rxtx_buf_sizes {
> > +	RXTX_4K,
> > +	RXTX_64K,
> > +	RXTX_16K
> > +};
> > +
> > +/*
> > + * Number of the FF-A interfaces features descriptors
> > + * currently only FFA_RXTX_MAP descriptor is supported
> > + */
> > +#define FFA_FEATURE_DESC_CNT (1)
> > +
> > +/**
> > + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> > + * @rxbuf:	virtual address of the RX buffer
> > + * @txbuf:	virtual address of the TX buffer
> > + *
> > + * Data structure hosting the virtual addresses of the mapped RX/TX buffers
> > + * These addresses are used by the FF-A functions that use the RX/TX buffers
> > + */
> > +struct ffa_rxtxpair {
> > +	u64 rxbuf; /* virtual address */
> > +	u64 txbuf; /* virtual address */
> > +};
> > +
> > +/**
> > + * struct ffa_partition_desc - the secure partition descriptor
> > + * @info:	partition information
> > + * @UUID:	UUID
> > + *
> > + * Each partition has its descriptor containing the partitions information and the UUID
> > + */
> > +struct ffa_partition_desc {
> > +	struct ffa_partition_info info;
> > +	union ffa_partition_uuid UUID;
> > +};
> > +
> > +/**
> > + * struct ffa_partitions - descriptors for all secure partitions
> > + * @count:	The number of partitions descriptors
> > + * @descs	The partitions descriptors table
> > + *
> > + * This data structure contains the partitions descriptors table
> > + */
> > +struct ffa_partitions {
> > +	u32 count;
> > +	struct ffa_partition_desc *descs; /* virtual address */
> > +};
> > +
> > +/**
> > + * struct 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
> > + * @conduit:	The selected conduit
> > + * @invoke_ffa_fn:	The function executing the FF-A function
> > + * @features:	Table of the FF-A functions having features
> > + *
> > + * The driver data structure hosting all resident data.
> > + */
> > +struct ffa_prvdata {
> > +	struct udevice *dev;
> > +	u32 fwk_version;
> > +	u16 id;
> > +	struct ffa_partitions partitions;
> > +	struct ffa_rxtxpair pair;
> > +	enum ffa_conduit conduit;
> > +	invoke_ffa_fn_t invoke_ffa_fn;
> > +	struct ffa_features_desc features[FFA_FEATURE_DESC_CNT];
> > +};
> > +
> > +#endif
> > diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c
> > new file mode 100644
> > index 0000000000..09e4eb753a
> > --- /dev/null
> > +++ b/drivers/arm-ffa/core.c
> > @@ -0,0 +1,1349 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include "arm_ffa_prv.h"
> > +#include <asm/global_data.h>
> > +#include <asm/io.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 <log.h>
> > +#include <malloc.h>
> > +#include <mapmem.h>
> > +#include <string.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/**
> > + * The device private data structure containing all the resident
> > + * data read from secure world
> > + */
> > +struct ffa_prvdata __ffa_runtime_data ffa_priv_data = {0};
> > +
> > +/*
> > + * Driver functions
> > + */
> > +
> > +/**
> > + * ffa_get_device - create, bind and probe the arm_ffa device
> > + *
> > + * This boot time function makes sure the arm_ffa device is
> > + * created, bound to this driver, probed and ready to use.
> > + * Arm FF-A transport is implemented through a single u-boot
> > + * device managing the FF-A bus (arm_ffa).
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +int ffa_get_device(void)
> > +{
> > +	int ret;
> > +
> > +	if (ffa_priv_data.dev)
> > +		return FFA_ERR_STAT_SUCCESS;
> > +
> > +	ret = device_bind(dm_root(),
> > +			  DM_DRIVER_GET(arm_ffa),
> > +			  FFA_DRV_NAME,
> > +			  NULL,
> > +			  ofnode_null(),
> > +			  &ffa_priv_data.dev);
> > +	if (ret) {
> > +		ffa_priv_data.dev = NULL;
> > +		return ret;
> > +	}
> > +
> > +	/* The FF-A bus discovery succeeds when probing is successful */
> > +	ret = device_probe(ffa_priv_data.dev);
> > +	if (ret) {
> > +		ffa_err("can not probe  the device");
> > +		device_unbind(ffa_priv_data.dev);
> > +		ffa_priv_data.dev = NULL;
> > +		return ret;
> > +	}
> > +
> > +	return FFA_ERR_STAT_SUCCESS;
> > +}
> > +
> > +/**
> > + * ffa_get_version - FFA_VERSION handler function
> > + *
> > + * This is the boot time function that implements FFA_VERSION FF-A function
> > + * to get from the secure world the FF-A framework version
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_get_version(void)
> > +{
> > +	u16 major, minor;
> > +
> > +	FFA_DECLARE_ARGS;
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	a0 = FFA_VERSION;
> > +	a1 = FFA_VERSION_1_0;
> > +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> > +
> > +	if (res.a0 == FFA_ERR_STAT_NOT_SUPPORTED) {
> > +		ffa_err("A Firmware Framework implementation does not exist");
> > +		return -EOPNOTSUPP;
> > +	}
> > +
> > +	major = GET_FFA_MAJOR_VERSION(res.a0);
> > +	minor = GET_FFA_MINOR_VERSION(res.a0);
> > +
> > +	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> > +		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
> > +		ffa_info("Versions are compatible ");
> > +
> > +		ffa_priv_data.fwk_version = res.a0;
> > +
> > +		return FFA_ERR_STAT_SUCCESS;
> > +	}
> > +
> > +	ffa_info("Versions are incompatible ");
> 
> This is an error, perhaps better to use ffa_err() instead. And mention
> the versions in question also since the info level might be disabled.

Done. Please refer to v4 for the latest updates on that part.

> 
> > +	return -EPROTONOSUPPORT;
> > +}
> > +
> > +/**
> > + * ffa_get_endpoint_id - FFA_ID_GET handler function
> > + *
> > + * This is the boot time function that implements FFA_ID_GET FF-A function
> > + * to get from the secure world u-boot endpoint ID
> 
> This is to get the vm id from an eventual hypervisor, or 0 if there
> isn't any hypervisor.

The FF-A 1.0 spec says: ID value 0 must be returned at the Non-secure 
physical FF-A instance. In our case the Non-secure physical FF-A 
instance is u-boot. The comment in the function header is trying to
be as close as possible to what the spec is saying.

> 
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_get_endpoint_id(void)
> > +{
> > +	FFA_DECLARE_ARGS;
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	a0 = FFA_ID_GET;
> > +
> > +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> > +
> > +	switch (res.a0) {
> > +	case FFA_ERROR:
> > +	{
> > +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
> > +			ffa_err("This function is not implemented at this FF-A instance");
> > +			return -EOPNOTSUPP;
> > +		}
> > +
> > +		ffa_err("Undefined error code (%d)", ((int)res.a2));
> > +		return -EINVAL;
> > +	}
> 
> Are these extra braces really needed? Same below.

error handling has been redesigned to use error mappings. 
Please refer to v4: https://lore.kernel.org/all/20220926101723.9965-5-abdellatif.elkhlifi@arm.com/

> 
> > +	case FFA_SUCCESS:
> > +	{
> > +		ffa_priv_data.id = GET_SELF_ENDPOINT_ID(res.a2);
> > +		ffa_info("endpoint ID is %u", ffa_priv_data.id);
> > +
> > +		return FFA_ERR_STAT_SUCCESS;
> > +	}
> > +	default:
> > +	{
> > +		ffa_err("Undefined response function (0x%lx)", res.a0);
> > +		return -EINVAL;
> > +	}
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_get_features_desc - returns the features descriptor of the specified
> > + *						FF-A function
> > + * @func_id:	the FF-A function which the features are to be retrieved
> > + *
> > + * This is a boot time function that searches the features descriptor of the
> > + * specified FF-A function
> > + *
> > + * Return:
> > + *
> > + * When found, the address of the features descriptor is returned. Otherwise, NULL.
> > + */
> > +static struct ffa_features_desc *ffa_get_features_desc(u32 func_id)
> > +{
> > +	u32 desc_idx;
> > +
> > +	/*
> > +	 * search for the descriptor of the selected FF-A interface
> > +	 */
> > +	for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
> > +		if (ffa_priv_data.features[desc_idx].func_id == func_id)
> > +			return &ffa_priv_data.features[desc_idx];
> > +
> > +	return NULL;
> > +}
> > +
> > +/**
> > + * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP
> > + *							argument
> > + *
> > + * This is the boot time function that implements FFA_FEATURES FF-A function
> > + * to retrieve the FFA_RXTX_MAP features
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_get_rxtx_map_features(void)
> > +{
> > +	FFA_DECLARE_ARGS;
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	a0 = FFA_FEATURES;
> > +	a1 = FFA_RXTX_MAP;
> > +
> > +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> > +
> > +	switch (res.a0) {
> > +	case FFA_ERROR:
> > +	{
> > +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
> > +			ffa_err("FFA_RXTX_MAP is not implemented at this FF-A instance");
> > +			return -EOPNOTSUPP;
> > +		}
> > +
> > +		ffa_err("Undefined error code (%d)", ((int)res.a2));
> > +		return -EINVAL;
> > +	}
> > +	case FFA_SUCCESS:
> > +	{
> > +		u32 desc_idx;
> > +
> > +		/*
> > +		 * search for an empty descriptor
> > +		 */
> > +		for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
> > +			if (!ffa_priv_data.features[desc_idx].func_id) {
> > +				/*
> > +				 * populate the descriptor with
> > +				 * the interface features data
> > +				 */
> > +				ffa_priv_data.features[desc_idx].func_id =
> > +					FFA_RXTX_MAP;
> > +				ffa_priv_data.features[desc_idx].field1 =
> > +					res.a2;
> > +
> > +				ffa_info("FFA_RXTX_MAP features data 0x%lx",
> > +					 res.a2);
> 
> This seems a bit more complicated than necessary. How about just save
> the block size in a separate fields in ffa_priv_data? That would also
> make it easier to understand what this value is without looking it up in
> the spec to remind oneself.

Done in v4. rxtx_min_pages field has been added in the ffa_rxtxpair 
structure and replaces the older logic.

> 
> > +
> > +				return FFA_ERR_STAT_SUCCESS;
> > +			}
> > +
> > +		ffa_err("Cannot save FFA_RXTX_MAP features data. Descriptors table full");
> > +		return -ENOBUFS;
> > +	}
> > +	default:
> > +	{
> > +		ffa_err("Undefined response function (0x%lx)",
> > +			res.a0);
> > +		return -EINVAL;
> > +	}
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_get_rxtx_buffers_pages_cnt - reads from the features data descriptors
> > + *						the minimum number of pages in each of the RX/TX
> > + *						buffers
> > + * @buf_4k_pages: Pointer to the minimum number of pages
> > + *
> > + * This is the boot time function that  returns the minimum number of pages
> > + *  in each of the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * buf_4k_pages points to the returned number of pages
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_get_rxtx_buffers_pages_cnt(size_t *buf_4k_pages)
> > +{
> > +	struct ffa_features_desc *desc = NULL;
> > +
> > +	if (!buf_4k_pages)
> > +		return -EINVAL;
> > +
> > +	desc = ffa_get_features_desc(FFA_RXTX_MAP);
> > +	if (!desc)
> > +		return -EINVAL;
> > +
> > +	switch (desc->field1) {
> > +	case RXTX_4K:
> > +		*buf_4k_pages = 1;
> > +		break;
> > +	case RXTX_16K:
> > +		*buf_4k_pages = 4;
> > +		break;
> > +	case RXTX_64K:
> > +		*buf_4k_pages = 16;
> > +		break;
> > +	default:
> > +		ffa_err("RX/TX buffer size not supported");
> > +		return -EINVAL;
> > +	}
> > +
> > +	return FFA_ERR_STAT_SUCCESS;
> > +}
> > +
> > +/**
> > + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> > + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> > + *			  buffers
> > + *
> > + * This is the boot time function used to free the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_free_rxtx_buffers(size_t buf_4k_pages)
> > +{
> > +	efi_status_t free_rxbuf_ret, free_txbuf_ret;
> > +
> > +	ffa_info("Freeing RX/TX buffers");
> > +
> > +	free_rxbuf_ret = efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
> > +	free_txbuf_ret = efi_free_pages(ffa_priv_data.pair.txbuf, buf_4k_pages);
> > +
> > +	if (free_rxbuf_ret != EFI_SUCCESS || free_txbuf_ret != EFI_SUCCESS) {
> > +		ffa_err("Failed to free RX/TX buffers (rx: %lu , tx: %lu)",
> > +			free_rxbuf_ret,
> > +			free_txbuf_ret);
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_priv_data.pair.rxbuf = 0;
> > +	ffa_priv_data.pair.txbuf = 0;
> > +
> > +	return FFA_ERR_STAT_SUCCESS;
> > +}
> > +
> > +/**
> > + * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
> > + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> > + *			  buffers
> > + *
> > + * This is the boot time function used by ffa_map_rxtx_buffers to allocate
> > + * the RX/TX buffers before mapping them
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_alloc_rxtx_buffers(size_t buf_4k_pages)
> > +{
> > +#if CONFIG_IS_ENABLED(EFI_LOADER)
> > +
> > +	efi_status_t efi_ret;
> > +	void *virt_txbuf;
> > +	void *virt_rxbuf;
> > +
> > +	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
> > +		 buf_4k_pages);
> > +
> > +	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> > +				     EFI_BOOT_SERVICES_DATA,
> > +				     buf_4k_pages,
> > +				     &ffa_priv_data.pair.rxbuf);
> > +
> > +	if (efi_ret != EFI_SUCCESS) {
> > +		ffa_priv_data.pair.rxbuf = 0;
> > +		ffa_err("Failure to allocate RX buffer (EFI error: 0x%lx)",
> > +			efi_ret);
> > +
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("RX buffer at virtual address 0x%llx",
> > +		 ffa_priv_data.pair.rxbuf);
> > +
> > +	virt_rxbuf = (void *)ffa_priv_data.pair.rxbuf;
> > +
> > +	/*
> > +	 * make sure the buffer is clean before use
> > +	 */
> > +	memset(virt_rxbuf, 0, buf_4k_pages * SZ_4K);
> > +
> > +	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> > +				     EFI_RUNTIME_SERVICES_DATA,
> > +				     buf_4k_pages,
> > +				     &ffa_priv_data.pair.txbuf);
> > +
> > +	if (efi_ret != EFI_SUCCESS) {
> > +		efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
> > +		ffa_priv_data.pair.rxbuf = 0;
> > +		ffa_priv_data.pair.txbuf = 0;
> > +		ffa_err("Failure to allocate the TX buffer (EFI error: 0x%lx)"
> > +			, efi_ret);
> > +
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("TX buffer at virtual address 0x%llx",
> > +		 ffa_priv_data.pair.txbuf);
> > +
> > +	virt_txbuf = (void *)ffa_priv_data.pair.txbuf;
> > +
> > +	/*
> > +	 * make sure the buffer is clean before use
> > +	 */
> > +	memset(virt_txbuf, 0, buf_4k_pages * SZ_4K);
> > +
> > +	return FFA_ERR_STAT_SUCCESS;
> > +
> > +#else
> > +	return -ENOBUFS;
> > +#endif
> > +}
> > +
> > +/**
> > + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> > + * @buf_4k_pages: the minimum number of pages in each of the RX/TX
> > + *			  buffers
> > + *
> > + * This is the boot time function that implements FFA_RXTX_MAP FF-A function
> > + * to map the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_map_rxtx_buffers(size_t buf_4k_pages)
> > +{
> > +	int ret;
> > +
> > +	FFA_DECLARE_ARGS;
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	ret = ffa_alloc_rxtx_buffers(buf_4k_pages);
> > +	if (ret != FFA_ERR_STAT_SUCCESS)
> > +		return ret;
> > +
> > +	a0 = FFA_RXTX_MAP;
> > +	a1 = ffa_priv_data.pair.txbuf;
> > +	a2 = ffa_priv_data.pair.rxbuf;
> > +	a3 = buf_4k_pages;
> > +
> > +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> > +
> > +	switch (res.a0) {
> > +	case FFA_ERROR:
> > +	{
> > +		switch (((int)res.a2)) {
> > +		case FFA_ERR_STAT_INVALID_PARAMETERS:
> > +			ffa_err("One or more fields in input parameters is incorrectly encoded");
> > +			ret = -EPERM;
> > +			break;
> > +		case FFA_ERR_STAT_NO_MEMORY:
> > +			ffa_err("Not enough memory");
> > +			ret = -ENOMEM;
> > +			break;
> > +		case FFA_ERR_STAT_DENIED:
> > +			ffa_err("Buffer pair already registered");
> > +			ret = -EACCES;
> > +			break;
> > +		case FFA_ERR_STAT_NOT_SUPPORTED:
> > +			ffa_err("This function is not implemented at this FF-A instance");
> > +			ret = -EOPNOTSUPP;
> > +			break;
> > +		default:
> > +			ffa_err("Undefined error (%d)",
> > +				((int)res.a2));
> > +			ret = -EINVAL;
> > +		}
> 
> How about lookup table like in the kernel instead? It seems that this
> kind of translation will be needed a few times.

Done in v4.

> 
> 
> > +		break;
> > +	}
> > +	case FFA_SUCCESS:
> > +		ffa_info("RX/TX buffers mapped");
> > +		return FFA_ERR_STAT_SUCCESS;
> > +	default:
> > +		ffa_err("Undefined response function (0x%lx)",
> > +			res.a0);
> > +		ret = -EINVAL;
> > +	}
> > +
> > +	ffa_free_rxtx_buffers(buf_4k_pages);
> > +
> > +	return ret;
> > +}
> > +
> > +/**
> > + * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
> > + *
> > + * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function
> > + * to unmap the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_unmap_rxtx_buffers(void)
> > +{
> > +	FFA_DECLARE_ARGS;
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	a0 = FFA_RXTX_UNMAP;
> > +	a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id);
> > +
> > +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> > +
> > +	switch (res.a0) {
> > +	case FFA_ERROR:
> > +	{
> > +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
> > +			panic("[FFA] FFA_RXTX_UNMAP is not implemented at this FF-A instance\n");
> > +		else if (((int)res.a2) == FFA_ERR_STAT_INVALID_PARAMETERS)
> > +			panic("[FFA] There is no buffer pair registered on behalf of the caller\n");
> > +		else
> > +			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
> > +	}
> > +	case FFA_SUCCESS:
> > +	{
> > +		size_t buf_4k_pages = 0;
> > +		int ret;
> > +
> > +		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
> > +		if (ret != FFA_ERR_STAT_SUCCESS)
> > +			panic("[FFA] RX/TX buffers unmapped but failure in getting pages count\n");
> > +
> > +		ret = ffa_free_rxtx_buffers(buf_4k_pages);
> > +		if (ret != FFA_ERR_STAT_SUCCESS)
> > +			panic("[FFA] RX/TX buffers unmapped but failure in freeing the memory\n");
> > +
> > +		ffa_info("RX/TX buffers unmapped and memory freed");
> > +
> > +		return FFA_ERR_STAT_SUCCESS;
> > +	}
> > +	default:
> > +		panic("[FFA] Undefined response function (0x%lx)", res.a0);
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
> > + *
> > + * This is the boot time function that invokes FFA_RX_RELEASE FF-A function
> > + * to release the ownership of the RX buffer
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_release_rx_buffer(void)
> > +{
> > +	FFA_DECLARE_ARGS;
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	a0 = FFA_RX_RELEASE;
> > +
> > +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
> > +
> > +	switch (res.a0) {
> > +	case FFA_ERROR:
> > +	{
> > +		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
> > +			panic("[FFA] FFA_RX_RELEASE is not implemented at this FF-A instance\n");
> > +		else if (((int)res.a2) == FFA_ERR_STAT_DENIED)
> > +			panic("[FFA] Caller did not have ownership of the RX buffer\n");
> > +		else
> > +			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
> > +	}
> > +	case FFA_SUCCESS:
> > +		return FFA_ERR_STAT_SUCCESS;
> > +
> > +	default:
> > +		panic("[FFA] Undefined response function (0x%lx)\n", res.a0);
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_uuid_are_identical - checks whether two given UUIDs are identical
> > + * @uuid1: first UUID
> > + * @uuid2: second UUID
> > + *
> > + * This is a boot time function used by ffa_read_partitions_info to search
> > + * for a UUID in the partitions descriptors table
> > + *
> > + * Return:
> > + *
> > + * 1 when UUIDs match. Otherwise, 0
> > + */
> > +int ffa_uuid_are_identical(const union ffa_partition_uuid *uuid1,
> > +			   const union ffa_partition_uuid *uuid2)
> > +{
> > +	if (!uuid1 || !uuid2)
> > +		return 0;
> > +
> > +	return (!memcmp(uuid1, uuid2, sizeof(union ffa_partition_uuid)));
> > +}
> > +
> > +/**
> > + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> > + *							and saves it in the private structure
> > + * @count: The number of partitions queried
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + *
> > + * This is the boot time function that reads the partitions information
> > + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> > + * data structure.
> > + *
> > + * Return:
> > + *
> > + * The private data structure is updated with the partition(s) information
> > + * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
> > + */
> > +static int ffa_read_partitions_info(u32 count, union ffa_partition_uuid *part_uuid)
> > +{
> > +	if (!count) {
> > +		ffa_err("No partition detected");
> > +		return -ENODATA;
> > +	}
> > +
> > +	ffa_info("Reading partitions data from the RX buffer");
> > +
> > +#if CONFIG_IS_ENABLED(EFI_LOADER)
> > +
> > +	if (!part_uuid) {
> > +		/*
> > +		 * querying information of all partitions
> > +		 */
> > +		u64 data_pages;
> > +		u64 data_bytes;
> > +		efi_status_t efi_ret;
> > +		size_t buf_4k_pages = 0;
> > +		u32 desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +		int ret;
> > +
> > +		data_bytes = count * sizeof(struct ffa_partition_desc);
> > +		data_pages = efi_size_in_pages(data_bytes);
> > +
> > +		/*
> > +		 * get the RX buffer size in pages
> > +		 */
> > +		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
> > +		if (ret != FFA_ERR_STAT_SUCCESS) {
> > +			ffa_err("Can not get the RX buffer size (error %d)", ret);
> > +			return ret;
> > +		}
> > +
> > +		if (data_pages > buf_4k_pages) {
> > +			ffa_err("Partitions data size exceeds the RX buffer size:");
> > +			ffa_err("    Sizes in pages: data %llu , RX buffer %lu ",
> > +				data_pages,
> > +				buf_4k_pages);
> > +
> > +			return -ENOMEM;
> > +		}
> > +
> > +		efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> > +					     EFI_RUNTIME_SERVICES_DATA,
> > +					     data_pages,
> > +					     (u64 *)&ffa_priv_data.partitions.descs);
> > +
> > +		if (efi_ret != EFI_SUCCESS) {
> > +			ffa_priv_data.partitions.descs = NULL;
> > +
> > +			ffa_err("Cannot  allocate partitions data buffer (EFI error 0x%lx)",
> > +				efi_ret);
> > +
> > +			return -ENOBUFS;
> > +		}
> > +
> > +		/*
> > +		 * make sure the buffer is clean before use
> > +		 */
> > +		memset(ffa_priv_data.partitions.descs, 0,
> > +		       data_pages * SZ_4K);
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data.pair.rxbuf;
> > +
> > +		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
> > +			ffa_priv_data.partitions.descs[desc_idx].info =
> > +				parts_info[desc_idx];
> > +
> > +			ffa_info("Partition ID %x : info cached",
> > +				 ffa_priv_data.partitions.descs[desc_idx].info.id);
> > +		}
> > +
> > +		ffa_priv_data.partitions.count = count;
> > +
> > +		ffa_info("%d partition(s) found and cached", count);
> > +
> > +	} else {
> > +		u32 rx_desc_idx, cached_desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +		u8 desc_found;
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data.pair.rxbuf;
> > +
> > +		/*
> > +		 * search for the SP IDs read from the RX buffer
> > +		 * in the already cached SPs.
> > +		 * Update the UUID when ID found.
> > +		 */
> > +		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
> > +			desc_found = 0;
> > +
> > +			/*
> > +			 * search the current ID in the cached partitions
> > +			 */
> > +			for (cached_desc_idx = 0;
> > +			     cached_desc_idx < ffa_priv_data.partitions.count;
> > +			     cached_desc_idx++) {
> > +				/*
> > +				 * save the UUID
> > +				 */
> > +				if (ffa_priv_data.partitions.descs[cached_desc_idx].info.id ==
> > +				    parts_info[rx_desc_idx].id) {
> > +					ffa_priv_data.partitions.descs[cached_desc_idx].UUID =
> > +						*part_uuid;
> > +
> > +					desc_found = 1;
> > +					break;
> > +				}
> > +			}
> > +
> > +			if (!desc_found)
> > +				return -ENODATA;
> > +		}
> > +	}
> > +#else
> > +#warning "arm_ffa: reading FFA_PARTITION_INFO_GET data not implemented"
> > +#endif
> > +
> > +	return  FFA_ERR_STAT_SUCCESS;
> > +}
> > +
> > +/**
> > + * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET
> > + *							and saves partitions data
> 
> Strange indentation.
> 
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + * @pcount: Pointer to the number of partitions variable filled when querying
> > + *
> > + * This is the boot time function that executes the FFA_PARTITION_INFO_GET
> > + * to query the partitions data. Then, it calls ffa_read_partitions_info
> > + * to save the data in the private data structure.
> > + *
> > + * After reading the data the RX buffer is released using ffa_release_rx_buffer
> > + *
> > + * Return:
> > + *
> > + * When part_uuid is NULL, all partitions data are retrieved from secure world
> > + * When part_uuid is non NULL, data for partitions matching the given UUID are
> > + * retrieved and the number of partitions is returned
> > + * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
> > + */
> > +static int ffa_query_partitions_info(union ffa_partition_uuid *part_uuid,
> > +				     u32 *pcount)
> > +{
> > +	unsigned long a0 = 0;
> > +	union ffa_partition_uuid query_uuid = {0};
> > +	unsigned long a5 = 0;
> > +	unsigned long a6 = 0;
> > +	unsigned long a7 = 0;
> > +	struct arm_smccc_res res = {0};
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		panic("[FFA] no private data found\n");
> > +
> > +	a0 = FFA_PARTITION_INFO_GET;
> 
> Why no initialize a0 with with value above instead?

following the new interface design a0 is set at the invoke_ffa_fn callback call.
Please refer to v4 for the latest update on that.

> 
> > +
> > +	/*
> > +	 * If a UUID is specified. Information for one or more
> > +	 * partitions in the system is queried. Otherwise, information
> > +	 * for all installed partitions is queried
> > +	 */
> > +
> > +	if (part_uuid) {
> > +		if (!pcount)
> > +			return -EINVAL;
> > +
> > +		query_uuid = *part_uuid;
> > +	}
> > +
> > +	ffa_priv_data.invoke_ffa_fn(a0, query_uuid.words.a1, query_uuid.words.a2,
> > +				    query_uuid.words.a3, query_uuid.words.a4,
> > +				    a5, a6, a7, &res);
> > +
> > +	switch (res.a0) {
> > +	case FFA_ERROR:
> > +	{
> > +		switch (((int)res.a2)) {
> > +		case FFA_ERR_STAT_INVALID_PARAMETERS:
> > +			ffa_err("Unrecognized UUID");
> > +			return -EPERM;
> > +		case FFA_ERR_STAT_NO_MEMORY:
> > +			ffa_err("Results cannot fit in RX buffer of the caller");
> > +			return -ENOMEM;
> > +		case FFA_ERR_STAT_DENIED:
> > +			ffa_err("Callee is not in a state to handle this request");
> > +			return -EACCES;
> > +		case FFA_ERR_STAT_NOT_SUPPORTED:
> > +			ffa_err("This function is not implemented at this FF-A instance");
> > +			return -EOPNOTSUPP;
> > +		case FFA_ERR_STAT_BUSY:
> > +			ffa_err("RX buffer of the caller is not free");
> > +			return -EBUSY;
> > +		default:
> > +			ffa_err("Undefined error (%d)", ((int)res.a2));
> > +			return -EINVAL;
> > +		}
> > +	}
> > +	case FFA_SUCCESS:
> > +	{
> > +		int ret;
> > +
> > +		/*
> > +		 * res.a2 contains the count of partition information descriptors
> > +		 * populated in the RX buffer
> > +		 */
> > +		if (res.a2) {
> > +			ret = ffa_read_partitions_info(res.a2, part_uuid);
> > +			if (ret)
> > +				ffa_err("Failed to read partition(s) data , error (%d)", ret);
> > +		}
> > +
> > +		/*
> > +		 * return the SP count
> > +		 */
> > +		if (part_uuid) {
> > +			if (!ret)
> > +				*pcount = res.a2;
> > +			else
> > +				*pcount = 0;
> > +		}
> > +		/*
> > +		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
> > +		 * is assigned to the consumer (u-boot). So, we need to give
> > +		 * the ownership back to the secure world
> > +		 */
> 
> if there's a hypervisor we're returning the buffer to the hypervisor instead.
> how about "... back to the SPM or hypervisor"?

Done

> 
> > +		ret = ffa_release_rx_buffer();
> > +
> > +		if (!part_uuid && !res.a2) {
> > +			ffa_err("[FFA] no partition installed in the system");
> > +			return -ENODEV;
> > +		}
> > +
> > +		return ret;
> > +	}
> > +	default:
> > +		ffa_err("Undefined response function (0x%lx)", res.a0);
> > +		return  -EINVAL;
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
> > + * @func_data: Pointer to the FF-A function arguments container structure.
> > + * The passed arguments:
> > + * Mode 1: When getting from the driver the number of
> > + *	secure partitions:
> > + *	@data0_size: UUID size
> > + *	@data0: pointer to the UUID (little endian)
> > + *	@data1_size: size of the number of partitions
> > + *				variable
> > + *	@data1: pointer to the number of partitions
> > + *			 variable. The variable will be set
> > + *			 by the driver
> > + * Mode 2: When requesting the driver to return the
> > + *	partitions information:
> > + *	@data0_size: UUID size
> > + *	@data0: pointer to the UUID (little endian)
> > + *	@data1_size: size of the SPs information buffer
> > + *	@data1: pointer to SPs information buffer
> > + *		(allocated by the client).
> > + *		The buffer will be filled by the driver
> > + *
> > + * This is the boot time function that queries the secure partition data from
> > + * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
> > + * FF-A function to query the partition information from secure world.
> > + *
> > + * A client of the FF-A driver should know the UUID of the service it wants to
> > + * access. It should use the UUID to request the FF-A driver to provide the
> > + * partition(s) information of the service. The FF-A driver uses
> > + * PARTITION_INFO_GET to obtain this information. This is implemented through
> > + * ffa_get_partitions_info function.
> > + * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
> > + * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
> > + * They are not saved (already done). We only update the UUID in the cached area.
> > + * This assumes that partitions data does not change in the secure world.
> > + * Otherwise u-boot will have an outdated partition data. The benefit of caching
> > + * the information in the FF-A driver is to accommodate discovery after
> > + * ExitBootServices().
> > + *
> > + * When invoked through a client request, ffa_get_partitions_info should be
> > + * called twice. First call is to get from the driver the number of secure
> > + * partitions (SPs) associated to a particular UUID.
> > + * Then, the caller (client) allocates the buffer to host the SPs data and
> > + * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
> > + * buffer.
> > + *
> > + * To achieve the mechanism described above, ffa_get_partitions_info uses the
> > + * following functions:
> > + *		ffa_read_partitions_info
> > + *		ffa_query_partitions_info
> > + *
> > + * Return:
> > + *
> > + * @data1: When pointing to the number of partitions variable, the number is
> > + * set by the driver.
> > + * When pointing to the partitions information buffer, the buffer will be
> > + * filled by the driver.
> > + *
> > + * On success FFA_ERR_STAT_SUCCESS is returned. Otherwise, failure
> > + */
> > +static int ffa_get_partitions_info(struct ffa_interface_data *func_data)
> > +{
> > +	/*
> > +	 * fill_data:
> > +	 * 0: return the SP count
> > +	 * 1: fill SP data and return it to the caller
> > +	 * -1: undefined mode
> > +	 */
> > +	int fill_data = -1;
> > +	u32 desc_idx, client_desc_idx;
> > +	union ffa_partition_uuid *part_uuid;
> > +	u32 client_desc_max_cnt;
> > +	u32 parts_found = 0;
> > +
> > +	if (!func_data) {
> > +		ffa_err("No function data provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs)
> > +		panic("[FFA] No partition installed\n");
> > +
> > +	if (func_data->data0_size == sizeof(union ffa_partition_uuid) &&
> > +	    func_data->data0 &&
> > +	    func_data->data1_size == sizeof(u32) &&
> > +	    func_data->data1) {
> > +		/*
> > +		 * data0 (in): pointer to UUID
> > +		 * data1 (in): pointer to SP count
> > +		 * Out: SP count returned in the count variable pointed by data1
> > +		 */
> > +
> > +		fill_data = 0;
> > +
> > +		ffa_info("Preparing for checking partitions count");
> > +
> > +	} else if ((func_data->data0_size == sizeof(union ffa_partition_uuid)) &&
> > +		   func_data->data0 &&
> > +		   (func_data->data1_size >= sizeof(struct ffa_partition_info)) &&
> > +		   !(func_data->data1_size % sizeof(struct ffa_partition_info)) &&
> > +		   func_data->data1) {
> > +		/*
> > +		 * data0 (in): pointer to UUID
> > +		 * data1 (in): pointer to SPs descriptors buffer
> > +		 *             (created by the client)
> > +		 * Out: SPs descriptors returned in the buffer
> > +		 *      pointed by data1
> > +		 */
> > +
> > +		fill_data = 1;
> > +
> > +		client_desc_idx = 0;
> > +
> > +		/*
> > +		 * number of empty descriptors preallocated by the caller
> > +		 */
> > +		client_desc_max_cnt =
> > +			func_data->data1_size / sizeof(struct ffa_partition_info);
> > +
> > +		ffa_info("Preparing for filling partitions info");
> > +
> > +	} else {
> > +		ffa_err("Invalid function arguments provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	part_uuid = (union ffa_partition_uuid *)func_data->data0;
> > +
> > +	ffa_info("Searching partitions using the provided UUID");
> > +
> > +	/*
> > +	 * search in the cached partitions
> > +	 */
> > +	for (desc_idx = 0;
> > +	     desc_idx < ffa_priv_data.partitions.count;
> > +	     desc_idx++) {
> > +		if (ffa_uuid_are_identical(&ffa_priv_data.partitions.descs[desc_idx].UUID,
> > +					   part_uuid)) {
> > +			ffa_info("Partition ID %x matches the provided UUID",
> > +				 ffa_priv_data.partitions.descs[desc_idx].info.id);
> > +
> > +			parts_found++;
> > +
> > +			if (fill_data) {
> > +				/*
> > +				 * trying to fill the partition info in data1
> > +				 */
> > +
> > +				if (client_desc_idx < client_desc_max_cnt) {
> > +					((struct ffa_partition_info *)
> > +					 func_data->data1)[client_desc_idx++] =
> > +						ffa_priv_data.partitions.descs[desc_idx].info;
> > +					continue;
> > +				}
> > +
> > +				ffa_err("Failed to fill the current descriptor client buffer full");
> > +				return -ENOBUFS;
> > +			}
> > +		}
> > +	}
> > +
> > +	if (!parts_found) {
> > +		int ret;
> > +
> > +		ffa_info("No partition found. Querying framework ...");
> > +
> > +		ret = ffa_query_partitions_info(part_uuid, &parts_found);
> > +
> > +		if (ret == FFA_ERR_STAT_SUCCESS) {
> > +			if (!fill_data) {
> > +				*((u32 *)func_data->data1) = parts_found;
> > +
> > +				ffa_info("Number of partition(s) found matching the UUID: %d",
> > +					 parts_found);
> > +			} else {
> > +				/*
> > +				 * we want to read SPs info
> > +				 */
> > +
> > +				/*
> > +				 * If SPs data filled, retry searching SP info again
> > +				 */
> > +				if (parts_found)
> > +					ret = ffa_get_partitions_info(func_data);
> > +				else
> > +					ret = -ENODATA;
> > +			}
> > +		}
> > +
> > +		return ret;
> > +	}
> > +
> > +	/* partition(s) found */
> > +	if (!fill_data)
> > +		*((u32 *)func_data->data1) = parts_found;
> > +
> > +	return FFA_ERR_STAT_SUCCESS;
> > +}
> > +
> > +/**
> > + * ffa_cache_partitions_info - Queries and saves all secure partitions data
> > + *
> > + * This is a boot time function that invokes FFA_PARTITION_INFO_GET FF-A
> > + * function to query from secure world all partitions information.
> > + *
> > + * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
> > + * All installed partitions information are returned. We cache them in the
> > + * resident private data structure and we keep the UUID field empty
> > + * (in FF-A 1.0 UUID is not provided by the partition descriptor)
> > + *
> > + * This function is called at the device probing level.
> > + * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_cache_partitions_info(void)
> > +{
> > +	return ffa_query_partitions_info(NULL, NULL);
> > +}
> > +
> > +/**
> > + * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> > + * @func_data: Pointer to the FF-A function arguments container structure.
> > + *					The passed arguments:
> > + *						@data0_size: partition ID size
> > + *						@data0: pointer to the partition ID
> > + *						@data1_size: exchanged data size
> > + *						@data1: pointer to the data buffer preallocated by
> > + *								the client (in/out)
> > + *
> > + * This is the runtime function that implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * FF-A functions.
> > + *
> > + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> > + * The response from the secure partition is handled by reading the
> > + * FFA_MSG_SEND_DIRECT_RESP arguments.
> > + *
> > + * The maximum size of the data that can be exchanged is 20 bytes which is
> > + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> > + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> 
> This API looks quite complicated. Wouldn't it be easier to let the
> caller supply the struct ffa_send_direct_data *msg pointer directly
> instead, like in the Linux kernel driver. The approach here prevents the
> compiler from helping with type checks etc.

This has been addressed following the new interface design and alignment with 
the kernel driver. Please refer to v4 for the latest updates on that.

> 
> > +static int __ffa_runtime ffa_msg_send_direct_req(struct ffa_interface_data
> > +						 *func_data)
> > +{
> > +	u16 dst_part_id;
> > +	unsigned long a0 = 0;
> > +	unsigned long a1 = 0;
> > +	unsigned long a2 = 0;
> > +	struct ffa_send_direct_data *msg;
> > +	struct arm_smccc_res res = {0};
> > +
> > +	if (!ffa_priv_data.invoke_ffa_fn)
> > +		return -ENODEV;
> > +
> > +	if (!func_data)
> > +		return -EINVAL;
> > +
> > +	/* No partition installed */
> > +	if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs)
> > +		return -ENODEV;
> > +
> > +	/* Undefined interface parameters */
> > +	if (func_data->data0_size != sizeof(u16) ||
> > +	    !func_data->data0 ||
> > +	    func_data->data1_size != FFA_MSG_SEND_DIRECT_MAX_SIZE ||
> 
> FFA_MSG_SEND_DIRECT_MAX_SIZE? It's more like FFA_MSG_SEND_DIRECT_ONLY_SIZE.
> 
> > +	    !func_data->data1)
> > +		return -EINVAL;
> > +
> > +	dst_part_id = *((u16 *)func_data->data0);
> > +	msg = func_data->data1;
> > +
> > +	a0 = FFA_MSG_SEND_DIRECT_REQ;
> > +
> > +	a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id) |
> > +		PREP_PART_ENDPOINT_ID(dst_part_id);
> > +
> > +	ffa_priv_data.invoke_ffa_fn(a0, a1, a2,
> > +				    msg->a3,
> > +				    msg->a4,
> > +				    msg->a5,
> > +				    msg->a6,
> > +				    msg->a7,
> > +				    &res);
> > +
> > +	while (res.a0 == FFA_INTERRUPT)
> > +		ffa_priv_data.invoke_ffa_fn(FFA_RUN, res.a1,
> > +					    0, 0, 0, 0, 0, 0,
> > +					    &res);
> > +
> > +	switch (res.a0) {
> > +	case FFA_ERROR:
> > +	{
> > +		switch (((int)res.a2)) {
> > +		case FFA_ERR_STAT_INVALID_PARAMETERS:
> > +			/* Invalid endpoint ID or non-zero reserved register */
> > +			return -EPERM;
> > +		case FFA_ERR_STAT_ABORTED:
> > +			/* Message target ran into unexpected error and has aborted */
> > +			return -ECONNABORTED;
> > +		case FFA_ERR_STAT_DENIED:
> > +			/* Callee is not in a state to handle this request */
> > +			return -EACCES;
> > +		case FFA_ERR_STAT_NOT_SUPPORTED:
> > +			/* This function is not implemented at this FF-A instance */
> > +			return -EOPNOTSUPP;
> > +		case FFA_ERR_STAT_BUSY:
> > +			/* Message target is busy */
> > +			return -EBUSY;
> > +		default:
> > +			/* Undefined error */
> > +			return -ENXIO;
> > +		}
> > +	}
> > +	case FFA_SUCCESS:
> > +
> > +		/* Message sent with no response */
> > +		return FFA_ERR_STAT_SUCCESS;
> > +
> > +	case FFA_MSG_SEND_DIRECT_RESP:
> > +
> > +		/*
> > +		 * Message sent with response
> > +		 * extract the 32-bit wide return data
> > +		 */
> > +		msg->a3 = (u32)res.a3;
> > +		msg->a4 = (u32)res.a4;
> > +		msg->a5 = (u32)res.a5;
> > +		msg->a6 = (u32)res.a6;
> > +		msg->a7 = (u32)res.a7;
> > +
> > +		return FFA_ERR_STAT_SUCCESS;
> > +
> > +	default:
> > +		/* Undefined response function */
> > +		return -ENOENT;
> > +	}
> > +}
> > +
> > +/**
> > + * invoke_ffa_drv_api - The driver dispatcher function
> > + * @func_id:	The FF-A function to be used
> > + * @func_data:  Pointer to the FF-A function arguments container
> > + *					structure. This also includes pointers to the
> > + *					returned data needed by clients.
> > + * The dispatcher is a runtime function that selects the FF-A function handler
> > + * based on the input FF-A function ID.
> > + * The input arguments are passed to the handler function.
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +int __ffa_runtime invoke_ffa_drv_api(u32 func_id,
> > +				     struct ffa_interface_data *func_data)
> > +{
> > +	if (!ffa_priv_data.dev)
> > +		return -ENODEV;
> > +
> 
> I don't see the point with this funnel layer. It would in my opinion be
> easier to have one function pointer for each of the provided FF-A
> functions.
> 
> I wouldn't mind if the interface was a bit more like the interface
> provided in the Linux kernel, at least the parts we're going to support
> here. It would for sure help later when updating the OP-TEE driver to
> use this FF-A driver.

This has been addressed following the new interface design and 
alignment with the kernel driver. Please refer to v4 for the 
latest updates on that. ffa_bus_ops has been introduced and 
contains all the exported callbacks.

> 
> > +	switch (func_id) {
> > +	case FFA_PARTITION_INFO_GET:
> > +		return ffa_get_partitions_info(func_data);
> > +	case FFA_RXTX_UNMAP:
> > +		return ffa_unmap_rxtx_buffers();
> > +	case FFA_MSG_SEND_DIRECT_REQ:
> > +		return ffa_msg_send_direct_req(func_data);
> > +	default:
> > +		/* Undefined FF-A interface */
> > +		return -EINVAL;
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_set_conduit - Set the conduit
> > + *
> > + * This boot time function clears the private data structure and sets the conduit
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_set_conduit(void)
> > +{
> > +	ffa_priv_data.conduit = FFA_CONDUIT_SMC;
> > +
> > +	ffa_priv_data.invoke_ffa_fn = arm_ffa_smccc_smc;
> > +
> > +	ffa_info("Conduit is SMC");
> 
> What if there's a hypervisor? Then HVC should be used instead.

We are only supporting SMC at this stage

> 
> > +
> > +	return FFA_ERR_STAT_SUCCESS;
> > +}
> > +
> > +/**
> > + * ffa_probe - The driver probe function
> > + * @dev:	the arm_ffa device
> > + *
> > + * Probing is done at boot time and triggered by the uclass device discovery.
> > + * At probe level the following actions are done:
> > + *	- setting the conduit
> > + *	- querying the FF-A framework version
> > + *	- querying from secure world the u-boot endpoint ID
> > + *	- querying from secure world the supported features of the specified FF-A calls
> > + *	- mapping the RX/TX buffers
> > + *	- querying from secure world all the partitions information
> > + *
> > + * All data queried from secure world is saved in the resident private data structure.
> > + *
> > + * The probe will fail if either FF-A framework is not detected or the
> > + * FF-A requests are not behaving correctly. This ensures that the
> > + * driver is not installed and its operations are not exported to the clients.
> > + * However, once the driver is successfully probed and an FF-A anomaly is
> > + * detected when clients invoke the driver operations, the driver cause
> > + * u-boot to panic because the client would not know what to do in such conditions.
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +static int ffa_probe(struct udevice *dev)
> > +{
> > +	int ret;
> > +	size_t buf_4k_pages = 0;
> > +
> > +	ret = ffa_set_conduit();
> > +	if (ret != FFA_ERR_STAT_SUCCESS)
> > +		return ret;
> > +
> > +	ret = ffa_get_version();
> > +	if (ret != FFA_ERR_STAT_SUCCESS)
> > +		return ret;
> > +
> > +	ret = ffa_get_endpoint_id();
> > +	if (ret != FFA_ERR_STAT_SUCCESS)
> > +		return ret;
> > +
> > +	ret = ffa_get_rxtx_map_features();
> > +	if (ret != FFA_ERR_STAT_SUCCESS)
> > +		return ret;
> > +
> > +	ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
> > +	if (ret != FFA_ERR_STAT_SUCCESS)
> > +		return ret;
> > +
> > +	ret = ffa_map_rxtx_buffers(buf_4k_pages);
> 
> This function only suceeds if compiled with EFI runtime support, so probing will always fail without EFI runtime support.
> 
> If compiled with EFI runtime support, how is this supposed to work with
> the kernel FF-A driver? The FF-A framework only supports one buffer pair
> per component and I don't see where the buffer pair is freed when U-Boot
> is done.

From patchset v3, FF-A core driver has been decoupled from EFI. It can 
be compiled without EFI support. Please refer to v4 for the latest work 
on that. Freeing the RX/TX buffers is done in 2 locations.

1/ When RX/TX buffers are unmapped at ExitBootServices(). At EFI runtime 
   RX/TX buffers created by u-boot do not exist anymore.
2/ When the arm_ffa device is removed (please see ffa_remove function)

> 
> > +	if (ret != FFA_ERR_STAT_SUCCESS)
> > +		return ret;
> > +
> > +	ret = ffa_cache_partitions_info();
> > +	if (ret != FFA_ERR_STAT_SUCCESS) {
> > +		ffa_free_rxtx_buffers(buf_4k_pages);
> > +		return ret;
> > +	}
> > +
> > +	return FFA_ERR_STAT_SUCCESS;
> > +}
> > +
> > +/**
> > + * ffa_drv_ops - The driver operations runtime structure
> > + * @invoke_func:	The driver dispatcher
> > + */
> > +struct ffa_ops __ffa_runtime_data ffa_drv_ops = {
> > +	.invoke_func = invoke_ffa_drv_api
> > +};
> > +
> > +/**
> > + * ffa_device_get_ops - driver operations getter
> > + *
> > + * Return:
> > + * This runtime function returns a pointer to the driver operations structure
> > + */
> > +const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void)
> > +{
> > +	return &ffa_drv_ops;
> > +}
> > +
> > +/**
> > + * Declaring the arm_ffa driver under UCLASS_FFA
> > + */
> > +
> > +U_BOOT_DRIVER(arm_ffa) = {
> > +	.name		= FFA_DRV_NAME,
> > +	.id		= UCLASS_FFA,
> > +	.probe		= ffa_probe,
> > +};
> > diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> > new file mode 100644
> > index 0000000000..98db01ee72
> > --- /dev/null
> > +++ b/include/arm_ffa.h
> > @@ -0,0 +1,190 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_H
> > +#define __ARM_FFA_H
> > +
> > +#include <linux/arm-smccc.h>
> > +#include <linux/printk.h>
> > +
> > +/*
> > + * This header is public. It can be used by clients to access
> > + * data structures and definitions they need
> > + */
> > +
> > +/*
> > + * Macros for displaying logs
> > + */
> > +
> > +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +
> > +/*
> > + * The driver operations success error code
> > + */
> > +#define FFA_ERR_STAT_SUCCESS				(0)
> > +
> > +#if CONFIG_IS_ENABLED(EFI_LOADER)
> > +
> > +#include <efi_loader.h>
> > +
> > +/*
> > + * __ffa_runtime_data and __ffa_runtime - controls whether data/code are
> > + * available after calling the EFI ExitBootServices service.
> > + * Data/code tagged with these keywords are resident (available at boot time and
> > + * at runtime)
> > + */
> > +
> > +#define __ffa_runtime_data __efi_runtime_data
> > +#define __ffa_runtime __efi_runtime
> > +
> > +#else
> > +
> > +#define __ffa_runtime_data
> > +#define __ffa_runtime
> > +
> > +#endif
> > +
> > +/*
> > + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> > + */
> > +
> > +#define FFA_SMC(calling_convention, func_num)				\
> > +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
> > +			   ARM_SMCCC_OWNER_STANDARD, (func_num))
> > +
> > +#define FFA_SMC_32(func_num)	FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> > +
> > +#define FFA_VERSION				FFA_SMC_32(0x63)
> > +#define FFA_ID_GET				FFA_SMC_32(0x69)
> > +#define FFA_FEATURES				FFA_SMC_32(0x64)
> > +#define FFA_PARTITION_INFO_GET				FFA_SMC_32(0x68)
> 
> Too much indentation, same below
> 
> > +#define FFA_RXTX_MAP				FFA_SMC_32(0x66)
> > +#define FFA_RXTX_UNMAP				FFA_SMC_32(0x67)
> > +#define FFA_RX_RELEASE				FFA_SMC_32(0x65)
> > +#define FFA_MSG_SEND_DIRECT_REQ				FFA_SMC_32(0x6F)
> > +#define FFA_MSG_SEND_DIRECT_RESP				FFA_SMC_32(0x70)
> > +#define FFA_RUN				FFA_SMC_32(0x6D)
> > +#define FFA_ERROR				FFA_SMC_32(0x60)
> > +#define FFA_SUCCESS				FFA_SMC_32(0x61)
> > +#define FFA_INTERRUPT				FFA_SMC_32(0x62)
> > +
> > +/*
> > + * struct ffa_partition_info - Partition information descriptor
> > + * @id:	Partition ID
> > + * @exec_ctxt:	Execution context count
> > + * @properties:	Partition properties
> > + *
> > + * Data structure containing information about partitions instantiated in the system
> > + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> > + */
> > +struct  __packed ffa_partition_info {
> > +	u16 id;
> > +	u16 exec_ctxt;
> > +/* partition supports receipt of direct requests */
> > +#define FFA_PARTITION_DIRECT_RECV	BIT(0)
> > +/* partition can send direct requests. */
> > +#define FFA_PARTITION_DIRECT_SEND	BIT(1)
> > +/* partition can send and receive indirect messages. */
> > +#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
> > +	u32 properties;
> > +};
> > +
> > +/*
> > + * struct ffa_send_direct_data - Data structure hosting the data
> > + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * @a3-a7:	Data read/written from/to w3-w7 registers
> > + *
> > + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> > + * or read from FFA_MSG_SEND_DIRECT_RESP
> > + */
> > +struct __packed ffa_send_direct_data {
> > +	u32 a3; /* w3 */
> > +	u32 a4; /* w4 */
> > +	u32 a5; /* w5 */
> > +	u32 a6; /* w6 */
> > +	u32 a7; /* w7 */
> > +};
> > +
> > +#define FFA_MSG_SEND_DIRECT_MAX_SIZE (sizeof(struct ffa_send_direct_data))
> > +
> > +/* UUID data size */
> > +#define UUID_SIZE (16)
> > +
> > +/*
> > + * union ffa_partition_uuid - Data union hosting the UUID
> > + *							transmitted by FFA_PARTITION_INFO_GET
> > + * @words:	data structure giving 32-bit words access to the UUID data
> > + * @bytes:	data structure giving byte access to the UUID data
> > + *
> > + * The structure holds little-endian UUID data.
> > + */
> > +union ffa_partition_uuid {
> > +	struct __packed words {
> > +	u32 a1; /* w1 */
> > +	u32 a2; /* w2 */
> > +	u32 a3; /* w3 */
> > +	u32 a4; /* w4 */
> > +	} words;
> > +	u8 bytes[UUID_SIZE];
> > +};
> > +
> > +/**
> > + * struct ffa_interface_data - generic FF-A interface data structure used to exchange
> > + *							data between user layers and the 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 user layers can pass various types of data with different sizes.
> > + * The driver internal functions can detect the nature of this data, verfy compliance
> > + * then execute the request when appropriate.
> > + */
> > +struct ffa_interface_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 */
> > +};
> > +
> > +/**
> > + * struct ffa_ops - The driver operations structure
> > + * @invoke_func:	function pointer to the invoke function
> > + *
> > + * The data structure providing all the operations supported by the driver.
> > + * This structure is resident.
> > + */
> > +struct ffa_ops {
> > +	/* the driver dispatcher */
> > +	int (*invoke_func)(u32 func_id, struct ffa_interface_data *func_data);
> > +};
> > +
> > +/**
> > + * The device driver and the Uclass driver public functions
> > + */
> > +
> > +/**
> > + * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher
> > + */
> > +int __ffa_runtime ffa_get_invoke_func(u32 func_id,
> > +				      struct ffa_interface_data *func_data);
> > +
> > +/**
> > + * ffa_device_get_ops - driver operations getter
> > + */
> > +const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void);
> > +
> > +/**
> > + * ffa_get_device - create, bind and probe the arm_ffa device
> > + */
> > +int ffa_get_device(void);
> > +
> > +/**
> > + * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
> > + */
> > +int ffa_bus_discover(void);
> > +#endif
> > diff --git a/include/arm_ffa_helper.h b/include/arm_ffa_helper.h
> > new file mode 100644
> > index 0000000000..1cf68748f0
> > --- /dev/null
> > +++ b/include/arm_ffa_helper.h
> > @@ -0,0 +1,45 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_HELPER_H
> > +#define __ARM_FFA_HELPER_H
> > +
> > +#include <arm_ffa.h>
> > +
> > +/*
> > + * This header is public. Including this header provides all data structures
> > + * and definitions needed by clients to use the FF-A transport driver
> > + *
> > + * It also provides helper functions allowing to pass data and invoke  FF-A functions
> > + */
> > +
> > +/**
> > + * ffa_helper_get_partitions_info - Wrapper function for FFA_PARTITION_INFO_GET
> > + */
> > +int ffa_helper_get_partitions_info(struct ffa_interface_data *func_data);
> > +
> > +/**
> > + * ffa_helper_unmap_rxtx_buffers - Wrapper function for FFA_RXTX_UNMAP
> > + */
> > +int ffa_helper_unmap_rxtx_buffers(void);
> > +
> > +/**
> > + * ffa_helper_msg_send_direct_req - Wrapper function for
> > + *								FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + */
> > +int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data
> > +						 *func_data);
> > +
> > +/**
> > + * ffa_helper_bus_discover - Wrapper function for FF-A bus discovery
> > + */
> > +int ffa_helper_bus_discover(void);
> > +
> > +/**
> > + * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
> > + */
> > +int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin);
> > +#endif
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index 0e26e1d138..a1181b8f48 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -52,6 +52,7 @@ enum uclass_id {
> >  	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
> >  	UCLASS_ETH,		/* Ethernet device */
> >  	UCLASS_ETH_PHY,		/* Ethernet PHY device */
> > +	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
> >  	UCLASS_FIRMWARE,	/* Firmware */
> >  	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
> >  	UCLASS_GPIO,		/* Bank of general-purpose I/O pins */
> > diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> > index 7f2be23394..d58c7c104b 100644
> > --- a/include/linux/arm-smccc.h
> > +++ b/include/linux/arm-smccc.h
> > @@ -1,6 +1,8 @@
> >  /* SPDX-License-Identifier: GPL-2.0 */
> >  /*
> >   * Copyright (c) 2015, Linaro Limited
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  #ifndef __LINUX_ARM_SMCCC_H
> >  #define __LINUX_ARM_SMCCC_H
> > @@ -57,13 +59,17 @@
> >  #include <linux/types.h>
> >  /**
> >   * struct arm_smccc_res - Result from SMC/HVC call
> > - * @a0-a3 result values from registers 0 to 3
> > + * @a0-a7 result values from registers 0 to 7
> >   */
> >  struct arm_smccc_res {
> >  	unsigned long a0;
> >  	unsigned long a1;
> >  	unsigned long a2;
> >  	unsigned long a3;
> > +	unsigned long a4;
> > +	unsigned long a5;
> > +	unsigned long a6;
> > +	unsigned long a7;
> >  };
> >  
> >  /**
> > @@ -113,6 +119,26 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
> >  			unsigned long a5, unsigned long a6, unsigned long a7,
> >  			struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
> >  
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +/**
> > + * __arm_ffa_smccc_smc() - make SMC calls used for FF-A transport
> > + * @a0-a7: arguments passed in 64-bit registers x0 to x7
> > + * @res: result values from 64-bit registers x0 to x7
> > + *
> > + * This function is used to make SMC calls following SMC32 Calling Convention.
> > + * The content of the supplied parameters is copied to registers x0 to x7 prior
> > + * to the SMC instruction. The SMC call return data is 32-bit data read from
> > + * registers x0 tp x7.
> > + */
> > +asmlinkage void __arm_ffa_smccc_smc(unsigned long a0, unsigned long a1,
> > +				    unsigned long a2, unsigned long a3, unsigned long a4,
> > +				    unsigned long a5, unsigned long a6, unsigned long a7,
> > +				    struct arm_smccc_res *res);
> > +
> > +#define arm_ffa_smccc_smc __arm_ffa_smccc_smc
> > +
> > +#endif
> > +
> 
> How about leaving the FF-A bit out of this and only have generic SMCCC
> support? That would make it easier to bring in updates from Linux
> without reinventing the wheel. I would also be nice to know which
> version of the SMCCC we're using.

Done through this patch: https://lore.kernel.org/all/20220926101723.9965-2-abdellatif.elkhlifi@arm.com/

> 
> Cheers,
> Jens
> 
> >  #define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
> >  
> >  #define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
> > diff --git a/lib/Kconfig b/lib/Kconfig
> > index effe735365..9006e8d44c 100644
> > --- a/lib/Kconfig
> > +++ b/lib/Kconfig
> > @@ -845,6 +845,7 @@ config SMBIOS_PARSER
> >  source lib/efi/Kconfig
> >  source lib/efi_loader/Kconfig
> >  source lib/optee/Kconfig
> > +source lib/arm-ffa/Kconfig
> >  
> >  config TEST_FDTDEC
> >  	bool "enable fdtdec test"
> > diff --git a/lib/Makefile b/lib/Makefile
> > index 13fe5fb7a4..36f67cd94e 100644
> > --- a/lib/Makefile
> > +++ b/lib/Makefile
> > @@ -9,6 +9,7 @@ obj-$(CONFIG_EFI) += efi/
> >  obj-$(CONFIG_EFI_LOADER) += efi_driver/
> >  obj-$(CONFIG_EFI_LOADER) += efi_loader/
> >  obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/
> > +obj-$(CONFIG_ARM_FFA_TRANSPORT_HELPERS) += arm-ffa/
> >  obj-$(CONFIG_LZMA) += lzma/
> >  obj-$(CONFIG_BZIP2) += bzip2/
> >  obj-$(CONFIG_TIZEN) += tizen/
> > diff --git a/lib/arm-ffa/Kconfig b/lib/arm-ffa/Kconfig
> > new file mode 100644
> > index 0000000000..79acbc5a8f
> > --- /dev/null
> > +++ b/lib/arm-ffa/Kconfig
> > @@ -0,0 +1,6 @@
> > +config ARM_FFA_TRANSPORT_HELPERS
> > +	bool "Enable interface helpers for Arm Firmware Framework for Armv8-A"
> > +	depends on ARM_FFA_TRANSPORT
> > +	help
> > +	  User layers call FF-A interfaces using helper functions which
> > +	  pass the data and the FF-A function ID to the low level driver
> > diff --git a/lib/arm-ffa/Makefile b/lib/arm-ffa/Makefile
> > new file mode 100644
> > index 0000000000..cba625fde4
> > --- /dev/null
> > +++ b/lib/arm-ffa/Makefile
> > @@ -0,0 +1,8 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +#
> > +# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > +#
> > +
> > +# This file only gets included when CONFIG_ARM_FFA_TRANSPORT_HELPERS is set
> > +
> > +obj-y += arm_ffa_helper.o
> > diff --git a/lib/arm-ffa/arm_ffa_helper.c b/lib/arm-ffa/arm_ffa_helper.c
> > new file mode 100644
> > index 0000000000..a291b000a7
> > --- /dev/null
> > +++ b/lib/arm-ffa/arm_ffa_helper.c
> > @@ -0,0 +1,188 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include <common.h>
> > +#include <arm_ffa_helper.h>
> > +#include <uuid.h>
> > +
> > +/**
> > + * ffa_helper_get_partitions_info - Wrapper function for FFA_PARTITION_INFO_GET
> > + *
> > + * @func_data: Pointer to the FF-A function arguments container
> > + *				structure.
> > + *				The passed arguments:
> > + *					Mode 1: When getting from the driver the number of
> > + *						secure partitions:
> > + *						@data0_size: UUID size
> > + *						@data0: pointer to the UUID (little endian)
> > + *						@data1_size: size of the number of partitions
> > + *									variable
> > + *						@data1: pointer to the number of partitions
> > + *								 variable. The variable will be set
> > + *								 by the driver
> > + *					Mode 2: When requesting the driver to return the
> > + *						partitions information:
> > + *						@data0_size: UUID size
> > + *						@data0: pointer to the UUID (little endian)
> > + *						@data1_size: size of the SPs information buffer
> > + *						@data1: pointer to SPs information buffer
> > + *								(allocated by the client).
> > + *							The buffer will be filled by the driver
> > + *
> > + * This is the boot time function used by clients who wants to get from secure
> > + * world the partition(s) information.
> > + *
> > + * A client of the FF-A driver should know the UUID of the service it wants to
> > + * access. It should use the UUID to request the FF-A driver to provide the
> > + * partition(s) information of the service. The client should use
> > + * ffa_helper_get_partitions_info to pass the UUID information to the driver
> > + * which uses PARTITION_INFO_GET to obtain the partition(s) information.
> > + *
> > + * ffa_helper_get_partitions_info should be called twice. First call is to get
> > + * from the driver the number of secure partitions (SPs) associated to a
> > + * particular UUID. Then, the caller (client) allocates the buffer to host the
> > + * SPs data and issues a 2nd call. Then, the driver fills the SPs data in the
> > + * pre-allocated buffer.
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +int ffa_helper_get_partitions_info(struct ffa_interface_data *func_data)
> > +{
> > +	return ffa_get_invoke_func(FFA_PARTITION_INFO_GET, func_data);
> > +}
> > +
> > +/**
> > + * ffa_helper_unmap_rxtx_buffers - Wrapper function for FFA_RXTX_UNMAP
> > + *
> > + * This is the boot time function that allows clients to unmap the RX/TX
> > + * buffers
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +int ffa_helper_unmap_rxtx_buffers(void)
> > +{
> > +	return ffa_get_invoke_func(FFA_RXTX_UNMAP, NULL);
> > +}
> > +
> > +/**
> > + * ffa_helper_msg_send_direct_req - Wrapper function for
> > + *								FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * @func_data: Pointer to the FF-A function arguments container structure.
> > + * The passed arguments:
> > + *	@data0_size: partition ID size
> > + *	@data0: pointer to the partition ID
> > + *	@data1_size: exchanged data size
> > + *	@data1: pointer to the data buffer preallocated by the client (in/out)
> > + *
> > + * This is the runtime function that allows clients to send data to the secure
> > + * world partitions. The arm_ffa driver uses FFA_MSG_SEND_DIRECT_REQ to send the
> > + * data to the secure partition. The response from the secure partition is
> > + * handled internally by the driver using FFA_MSG_SEND_DIRECT_RESP and returned
> > + * to ffa_helper_msg_send_direct_req through @func_data
> > + *
> > + * The maximum size of the data that can be exchanged is 20 bytes which is
> > + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> > + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + *
> > + * The client should pre-allocate a buffer pointed by @data1 which the size
> > + * is sizeof(struct ffa_send_direct_data)
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data
> > +											 *func_data)
> > +{
> > +	return ffa_get_invoke_func(FFA_MSG_SEND_DIRECT_REQ, func_data);
> > +}
> > +
> > +/**
> > + * ffa_helper_bus_discover - Wrapper function for FF-A bus discovery
> > + *
> > + * This boot time function should be called to discover the FF-A bus and
> > + * probe the FF-A device.
> > + * To achieve that, this function is called automatically at initcalls
> > + * level (after u-boot relocation).
> > + *
> > + * Return:
> > + *
> > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
> > + */
> > +int ffa_helper_bus_discover(void)
> > +{
> > +	return ffa_bus_discover();
> > +}
> > +
> > +/**
> > + * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
> > + * @uuid_str:	UUID string in big endian format (36 bytes wide + '/0')
> > + * @uuid_bin:	preallocated 16 bytes UUID buffer in little endian format
> > + *
> > + * UUID binary format used by the FF-A framework (16 bytes):
> > + *
> > + * [LSB] 4B-2B-2B-2B-6B (little endian data fields)
> > + *
> > + * UUID string is 36 length of characters (36 bytes):
> > + *
> > + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
> > + * be                be      be       be      be
> > + *
> > + * where x is a hexadecimal character. Fields are separated by '-'s.
> > + * When converting to a binary UUID, these endianness rules apply:
> > + *     be: means the field in the string is considered a big endian hex number
> > + *         and should be converted to little endian binary format
> > + *
> > + * Return:
> > + *
> > + *    uuid_bin filled with little endian UUID data
> > + *    On success 0 is returned. Otherwise, failure code.
> > + */
> > +int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin)
> > +{
> > +	u16 tmp16 = 0;
> > +	u32 tmp32 = 0;
> > +	u64 tmp64 = 0;
> > +
> > +	if (!uuid_str_valid(uuid_str) || !uuid_bin)
> > +		return -EINVAL;
> > +
> > +	/*
> > +	 * reverse bytes from big to little endian
> > +	 */
> > +	tmp32 = simple_strtoul(uuid_str, NULL, 16);
> > +	memcpy(uuid_bin, &tmp32, 4);
> > +
> > +	/*
> > +	 * reverse bytes from big to little endian
> > +	 */
> > +	tmp16 = simple_strtoul(uuid_str + 9, NULL, 16);
> > +	memcpy(uuid_bin + 4, &tmp16, 2);
> > +
> > +	/*
> > +	 * reverse bytes from big to little endian
> > +	 */
> > +	tmp16 = simple_strtoul(uuid_str + 14, NULL, 16);
> > +	memcpy(uuid_bin + 6, &tmp16, 2);
> > +
> > +	/*
> > +	 * reverse bytes from big to little endian
> > +	 */
> > +	tmp16 = simple_strtoul(uuid_str + 19, NULL, 16);
> > +	memcpy(uuid_bin + 8, &tmp16, 2);
> > +
> > +	/*
> > +	 * reverse bytes from big to little endian
> > +	 */
> > +	tmp64 = simple_strtoull(uuid_str + 24, NULL, 16);
> > +	memcpy(uuid_bin + 10, (char *)&tmp64, 6);
> > +
> > +	return 0;
> > +}
> > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> > index 5bcb8253ed..cffa2c69d6 100644
> > --- a/lib/efi_loader/efi_boottime.c
> > +++ b/lib/efi_loader/efi_boottime.c
> > @@ -23,6 +23,10 @@
> >  #include <asm/setjmp.h>
> >  #include <linux/libfdt_env.h>
> >  
> > +#if defined(CONFIG_ARM_FFA_TRANSPORT)
> > +#include <arm_ffa_helper.h>
> > +#endif
> > +
> >  DECLARE_GLOBAL_DATA_PTR;
> >  
> >  /* Task priority level */
> > @@ -2114,6 +2118,10 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
> >  	struct efi_event *evt, *next_event;
> >  	efi_status_t ret = EFI_SUCCESS;
> >  
> > +#if defined(CONFIG_ARM_FFA_TRANSPORT)
> > +	int ffa_ret;
> > +#endif
> > +
> >  	EFI_ENTRY("%p, %zx", image_handle, map_key);
> >  
> >  	/* Check that the caller has read the current memory map */
> > @@ -2174,6 +2182,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
> >  		dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
> >  	}
> >  
> > +#if defined(CONFIG_ARM_FFA_TRANSPORT)
> > +	/* unmap FF-A RX/TX buffers */
> > +	ffa_ret = ffa_helper_unmap_rxtx_buffers();
> > +	if (ffa_ret)
> > +		debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n");
> > +	else
> > +		debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
> > +#endif
> > +
> >  	/* Patch out unsupported runtime function */
> >  	efi_runtime_detach();
> >  
> > -- 
> > 2.17.1
> > 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v3 2/4] arm64: smccc: clear the Xn registers after SMC calls
  2022-08-16 11:48                                 ` Jens Wiklander
@ 2022-09-26 11:33                                   ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 11:33 UTC (permalink / raw)
  To: Jens Wiklander; +Cc: u-boot, nd

On Tue, Aug 16, 2022 at 01:48:31PM +0200, Jens Wiklander wrote:
> On Mon, Aug 1, 2022 at 7:21 PM Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > set to zero the x0-x17 registers
> >
> > As per the SMCCC v1.2 spec, unused result and scratch registers can leak
> > information after an SMC call. We can mitigate against this risk by
> > returning zero in each register.
> >
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Cc: Tom Rini <trini@konsulko.com>
> > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > Cc: Jens Wiklander <jens.wiklander@linaro.org>
> > ---
> >  arch/arm/cpu/armv8/smccc-call.S | 20 ++++++++++++++++++++
> >  1 file changed, 20 insertions(+)
> >
> > diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
> > index ec6f299bc9..8ac3e461e4 100644
> > --- a/arch/arm/cpu/armv8/smccc-call.S
> > +++ b/arch/arm/cpu/armv8/smccc-call.S
> > @@ -84,6 +84,26 @@ ENDPROC(__arm_smccc_hvc)
> >         stp     x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
> >         stp     x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
> >
> > +       /* x0-x17 registers can leak information after an SMC or HVC call. Let's clear them */
> > +       mov     x0, xzr
> > +       mov     x1, xzr
> > +       mov     x2, xzr
> > +       mov     x3, xzr
> > +       mov     x4, xzr
> > +       mov     x5, xzr
> > +       mov     x6, xzr
> > +       mov     x7, xzr
> > +       mov     x8, xzr
> > +       mov     x9, xzr
> > +       mov     x10, xzr
> > +       mov     x11, xzr
> > +       mov     x12, xzr
> > +       mov     x13, xzr
> > +       mov     x14, xzr
> > +       mov     x15, xzr
> > +       mov     x16, xzr
> > +       mov     x17, xzr
> > +
> 
> Is this information leakage worse than the information leakage from an
> ordinary C function?
> My point is, is this needed?

The leakage we are referring to is data leakage across exception levels.
The intent is to prevent lower exception levels (EL1/EL0) to read the 
data exchanged at EL2.

The linux kernel clears the general purpose registers before switching 
to EL0. As far as I know u-boot doesn't. 

So, the code above makes sure the registers are cleared.
An improved version of this has been releases in this 
patch: https://lore.kernel.org/all/20220926101723.9965-3-abdellatif.elkhlifi@arm.com/

> 
> Thanks,
> Jens
> 
> >         /* Restore original x19 */
> >         ldp     xzr, x19, [sp], #16
> >         ret
> > --
> > 2.17.1
> >

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver
  2022-08-13  2:21                                 ` Simon Glass
@ 2022-09-26 11:37                                   ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 11:37 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, nd

On Fri, Aug 12, 2022 at 08:21:02PM -0600, Simon Glass wrote:
> Hi Abdellatif,
> 
> On Mon, 1 Aug 2022 at 11:21, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
> >
> > The Firmware Framework for Arm A-profile processors (FF-A)
> > describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World leveraging TrustZone
> > technology.
> >
> > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > querying the FF-A framework from the secure world.
> >
> > 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> > and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> >
> > In u-boot FF-A design, FF-A is considered as a discoverable bus.
> > The Secure World is considered as one entity to communicate with
> > using the FF-A bus. FF-A communication is handled by one device and
> > one instance (the bus). This FF-A driver takes care of all the
> > interactions between Normal world and Secure World.
> >
> > The driver exports its operations to be used by upper layers.
> >
> > Exported operations:
> >
> > - partition_info_get
> > - sync_send_receive
> > - rxtx_unmap
> >
> > This implementation provides an optional feature to copy the driver data
> > to EFI runtime area.
> 
> This is v2 but I don't see a change list?

Sorry for not including that in the cover letter. Here is the 
changelog for v2 [1].

From v3 upwards the changelog is included in the cover letter.

[1] https://lore.kernel.org/all/20220509105514.GA4201@e121910.cambridge.arm.com/

> 
> >
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Cc: Tom Rini <trini@konsulko.com>
> > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > Cc: Jens Wiklander <jens.wiklander@linaro.org>
> > ---
> >  MAINTAINERS                                |    6 +
> >  common/board_r.c                           |    7 +
> >  drivers/Kconfig                            |    2 +
> >  drivers/Makefile                           |    1 +
> >  drivers/arm-ffa/Kconfig                    |   33 +
> >  drivers/arm-ffa/Makefile                   |    7 +
> >  drivers/arm-ffa/arm-ffa-uclass.c           |   16 +
> >  drivers/arm-ffa/arm_ffa_prv.h              |  219 ++++
> >  drivers/arm-ffa/core.c                     | 1338 ++++++++++++++++++++
> >  drivers/arm-ffa/efi_ffa_runtime_data_mgr.c |   94 ++
> >  include/arm_ffa.h                          |  132 ++
> >  include/dm/uclass-id.h                     |    1 +
> >  include/uuid.h                             |    8 +
> >  lib/efi_loader/efi_boottime.c              |   17 +
> >  lib/uuid.c                                 |   65 +
> >  15 files changed, 1946 insertions(+)
> >  create mode 100644 drivers/arm-ffa/Kconfig
> >  create mode 100644 drivers/arm-ffa/Makefile
> >  create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
> >  create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
> >  create mode 100644 drivers/arm-ffa/core.c
> >  create mode 100644 drivers/arm-ffa/efi_ffa_runtime_data_mgr.c
> >  create mode 100644 include/arm_ffa.h
> >
> 
> I think this should be in an existing directory, or perhaps drivers/firmware.

Done in v4 (under drivers/firmware).

> 
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v5 00/10] introduce Arm FF-A support
  2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                   ` (9 preceding siblings ...)
  2022-09-26 10:17                                 ` [PATCH v4 10/10] arm_ffa: corstone1000: enable EFI " Abdellatif El Khlifi
@ 2022-09-26 14:08                                 ` Abdellatif El Khlifi
  2022-09-26 14:08                                   ` [PATCH v5 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                     ` (10 more replies)
  10 siblings, 11 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 14:08 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong, Xueliang Zhong

Moving the changelogs in each commit to the changes section.

No code change in v5.

Changelog of the major changes:
===========================

v5:

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/bind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-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>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Vishnu Banavath <vishnu.banavath@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (10):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  arm64: smccc: clear the Xn registers after SMC calls
  lib: uuid: introduce be_uuid_str_to_le_bin function
  arm_ffa: introduce Arm FF-A low-level driver
  arm_ffa: introduce armffa command
  arm_ffa: introduce the FF-A Sandbox driver
  arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: introduce FF-A MM communication
  arm_ffa: corstone1000: enable EFI MM communication

 MAINTAINERS                                   |   11 +
 arch/arm/cpu/armv8/cache.S                    |   19 +
 arch/arm/cpu/armv8/cache_v8.c                 |    6 +-
 arch/arm/cpu/armv8/smccc-call.S               |   62 +
 arch/arm/lib/asm-offsets.c                    |   14 +
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    2 +
 cmd/armffa.c                                  |  242 +++
 common/board_r.c                              |    9 +
 configs/corstone1000_defconfig                |    4 +
 configs/sandbox64_defconfig                   |    2 +
 configs/sandbox_defconfig                     |    2 +
 doc/README.ffa.drv                            |  160 ++
 doc/arch/sandbox.rst                          |    1 +
 drivers/Kconfig                               |    2 +
 drivers/Makefile                              |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   46 +
 drivers/firmware/arm-ffa/Makefile             |    8 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     |   16 +
 drivers/firmware/arm-ffa/arm_ffa_prv.h        |  201 +++
 drivers/firmware/arm-ffa/core.c               | 1358 +++++++++++++++++
 .../arm-ffa/efi_ffa_runtime_data_mgr.c        |   94 ++
 drivers/firmware/arm-ffa/sandbox.c            |  659 ++++++++
 .../firmware/arm-ffa/sandbox_arm_ffa_prv.h    |  144 ++
 include/arm_ffa.h                             |  127 ++
 include/configs/corstone1000.h                |    9 +
 include/dm/uclass-id.h                        |    4 +
 include/linux/arm-smccc.h                     |   43 +
 include/mm_communication.h                    |    9 +-
 include/sandbox_arm_ffa.h                     |   91 ++
 include/uuid.h                                |    8 +
 lib/efi_loader/Kconfig                        |   14 +-
 lib/efi_loader/efi_boottime.c                 |   22 +
 lib/efi_loader/efi_variable_tee.c             |  263 +++-
 lib/uuid.c                                    |   64 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   40 +
 test/dm/Makefile                              |    2 +
 test/dm/ffa.c                                 |  394 +++++
 39 files changed, 4156 insertions(+), 9 deletions(-)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/README.ffa.drv
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/firmware/arm-ffa/core.c
 create mode 100644 drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
 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/arm_ffa.h
 create mode 100644 include/sandbox_arm_ffa.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v5 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
@ 2022-09-26 14:08                                   ` Abdellatif El Khlifi
  2022-09-26 14:08                                   ` [PATCH v5 02/10] arm64: smccc: clear the Xn registers after SMC calls Abdellatif El Khlifi
                                                     ` (9 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 14:08 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

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>
---

Changelog:
===============

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

 arch/arm/cpu/armv8/smccc-call.S | 53 +++++++++++++++++++++++++++++++++
 arch/arm/lib/asm-offsets.c      | 14 +++++++++
 include/linux/arm-smccc.h       | 43 ++++++++++++++++++++++++++
 3 files changed, 110 insertions(+)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..ec6f299bc9 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
@@ -45,3 +47,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 22fd541f9a..1bc2d90faa 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,9 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -117,6 +120,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+	#ifdef CONFIG_ARM64
+		DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+		DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+		DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+		DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+		DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+		DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+		DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+		DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+		DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+	#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..9105031d55 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +72,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v5 02/10] arm64: smccc: clear the Xn registers after SMC calls
  2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2022-09-26 14:08                                   ` [PATCH v5 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2022-09-26 14:08                                   ` Abdellatif El Khlifi
  2022-09-30  9:48                                     ` Jens Wiklander
  2022-09-26 14:08                                   ` [PATCH v5 03/10] lib: uuid: introduce be_uuid_str_to_le_bin function Abdellatif El Khlifi
                                                     ` (8 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 14:08 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong

set to zero the x0-x17 registers

As per the SMCCC v1.2 spec, unused result and scratch registers
can leak information after an SMC call. We can mitigate against
this risk by returning zero in each register.

The leakage we are referring to is data leakage across exception
levels. The intent is to prevent lower exception levels (EL1/EL0)
from reading the SMC data exchanged at EL2.

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>
---

Changelog:
===============

v4:

* move the clearing code into a new macro: clear_gp_regs

v3:

* clear the Xn registers after SMC calls


 arch/arm/cpu/armv8/smccc-call.S | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index ec6f299bc9..32f3eb8eeb 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -50,6 +50,12 @@ ENDPROC(__arm_smccc_hvc)
 
 #ifdef CONFIG_ARM64
 
+	.macro	clear_gp_regs
+	.irp	n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17
+	mov	x\n, xzr
+	.endr
+	.endm
+
 	.macro SMCCC_1_2 instr
 	/* Save `res` and free a GPR that won't be clobbered */
 	stp     x1, x19, [sp, #-16]!
@@ -84,6 +90,9 @@ ENDPROC(__arm_smccc_hvc)
 	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
 	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
 
+	/* x0-x17 registers can leak information after an SMC or HVC call. Let's clear them */
+	clear_gp_regs
+
 	/* Restore original x19 */
 	ldp     xzr, x19, [sp], #16
 	ret
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v5 03/10] lib: uuid: introduce be_uuid_str_to_le_bin function
  2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2022-09-26 14:08                                   ` [PATCH v5 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2022-09-26 14:08                                   ` [PATCH v5 02/10] arm64: smccc: clear the Xn registers after SMC calls Abdellatif El Khlifi
@ 2022-09-26 14:08                                   ` Abdellatif El Khlifi
  2022-09-26 14:08                                   ` [PATCH v5 04/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
                                                     ` (7 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 14:08 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong

convert big endian UUID string to little endian buffer

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>
---

Changelog:
===============

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

 include/uuid.h |  8 +++++++
 lib/uuid.c     | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..ad3af350f9 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,8 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +46,10 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * be_uuid_str_to_le_bin - Converts a big endian UUID string to a little endian buffer
+ */
+int be_uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 465e1ac38f..15a9ab49d5 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -346,6 +348,68 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * be_uuid_str_to_le_bin - Converts a big endian UUID string to a little endian buffer
+ * @uuid_str:	UUID string in big endian format (36 bytes wide + '/0')
+ * @uuid_bin:	preallocated 16 bytes UUID buffer in little endian format
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ * be		     be	     be	      be      be
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a binary UUID, these endianness rules apply:
+ *     be: means the field in the string is considered a big endian hex number
+ *	   and should be converted to little endian binary format
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int be_uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16 = 0;
+	u32 tmp32 = 0;
+	u64 tmp64 = 0;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp32 = simple_strtoul(uuid_str, NULL, 16);
+	memcpy(uuid_bin, &tmp32, 4);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 9, NULL, 16);
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 14, NULL, 16);
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 19, NULL, 16);
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp64 = simple_strtoull(uuid_str + 24, NULL, 16);
+	memcpy(uuid_bin + 10, (char *)&tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v5 04/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                     ` (2 preceding siblings ...)
  2022-09-26 14:08                                   ` [PATCH v5 03/10] lib: uuid: introduce be_uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2022-09-26 14:08                                   ` Abdellatif El Khlifi
  2022-10-03  8:49                                     ` Jens Wiklander
  2022-09-26 14:08                                   ` [PATCH v5 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                     ` (6 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 14:08 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong

Add the driver implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
and FFA_MSG_SEND_DIRECT_{REQ, RESP}.

In u-boot FF-A design, FF-A is considered as a discoverable bus.
The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- partition_info_get
- sync_send_receive
- rxtx_unmap

This implementation provides an optional feature to copy the driver data
to EFI runtime area.

[1]: https://developer.arm.com/documentation/den0077/latest/

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>
---

Changelog:
===============

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_bind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the u-boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

 MAINTAINERS                                   |    7 +
 common/board_r.c                              |    9 +
 doc/README.ffa.drv                            |  160 ++
 drivers/Kconfig                               |    2 +
 drivers/Makefile                              |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   39 +
 drivers/firmware/arm-ffa/Makefile             |    7 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     |   16 +
 drivers/firmware/arm-ffa/arm_ffa_prv.h        |  196 +++
 drivers/firmware/arm-ffa/core.c               | 1344 +++++++++++++++++
 .../arm-ffa/efi_ffa_runtime_data_mgr.c        |   94 ++
 include/arm_ffa.h                             |  127 ++
 include/dm/uclass-id.h                        |    4 +
 lib/efi_loader/efi_boottime.c                 |   15 +
 14 files changed, 2021 insertions(+)
 create mode 100644 doc/README.ffa.drv
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/firmware/arm-ffa/core.c
 create mode 100644 drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
 create mode 100644 include/arm_ffa.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 83346183ee..02b84d5074 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -248,6 +248,13 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	doc/README.ffa.drv
+F:	drivers/firmware/arm-ffa/
+F:	include/arm_ffa.h
+
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/common/board_r.c b/common/board_r.c
index 56eb60fa27..8c99faddfd 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -7,6 +7,8 @@
  * (C) Copyright 2002
  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2022 ARM Limited
  */
 
 #include <common.h>
@@ -66,6 +68,10 @@
 #include <efi_loader.h>
 #include <relocate.h>
 
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+#include <arm_ffa.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 ulong monitor_flash_len;
@@ -770,6 +776,9 @@ static init_fnc_t init_sequence_r[] = {
 	INIT_FUNC_WATCHDOG_RESET
 	initr_net,
 #endif
+#ifdef CONFIG_ARM_FFA_TRANSPORT
+	ffa_bus_discover,
+#endif
 #ifdef CONFIG_POST
 	initr_post,
 #endif
diff --git a/doc/README.ffa.drv b/doc/README.ffa.drv
new file mode 100644
index 0000000000..1c0a33deb8
--- /dev/null
+++ b/doc/README.ffa.drv
@@ -0,0 +1,160 @@
+Arm FF-A Driver
+====================
+
+Introduction
+--------------------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software sandboxes to communicate with each other. A sandbox aka partition could
+be a VM in the Normal or Secure world, an application in S-EL0, or a Trusted OS in S-EL1.
+
+This FF-A driver implements the interfaces to communicate with partitions in the Secure world aka Secure partitions (SPs).
+
+The driver specifically focuses on communicating with SPs that isolate portions of EFI runtime services that must run in a
+protected environment which is inaccessible by the Host OS or Hypervisor. Examples of such services are set/get variables.
+
+FF-A driver uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest.
+- Access an SP's service through communication protocols e.g. EFI MM communication protocol.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the driver relies on FF-A specification v1.0 and uses SMC32 calling convention.
+
+The driver has been tested with Optee OS which supports SMC32 for most of the SMC ABIs.
+
+For more details please refer to: https://developer.arm.com/documentation/den0077/a/?lang=en
+
+The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
+
+For more details please refer to: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+CONFIG_ARM_FFA_TRANSPORT
+    Enables the FF-A bus driver. Turn this on if you want to use FF-A communication.
+
+CONFIG_ARM_FFA_EFI_RUNTIME_MODE
+    Optional config that enables EFI runtime support for FF-A data and code.
+    ffa_copy_runtime_data allows to copy the FF-A driver data structures to EFI runtime data section.
+    Turning the config on makes ffa_copy_runtime_data available for use and the driver code placed at EFI runtime code section.
+    Call ffa_copy_runtime_data at the event on which you want the FF-A data to be copied (example: at ExitBootServices).
+
+CONFIG_SANDBOX_FFA
+    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under Sandbox and provides
+    functional tests for FF-A.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the expected arguments from the ABI.
+
+The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is giving back to the u-boot FF-A driver (non secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs in the driver.
+
+FF-A bus discovery in u-boot
+-------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is automatically discovered at initcall level (after u-boot relocation).
+
+The function that triggers the discovery process is ffa_bus_discover.
+
+ffa_bus_discover creates, binds and probes the arm_ffa device using device_{bind, probe} APIs.
+
+When the device is probed, ffa_probe is called which tries to communicate with the secure world or hypervisor.
+
+The FF-A bus is usable when these checks succeed:
+
+- querying the FF-A framework version
+- querying from secure world the u-boot endpoint ID
+- querying from secure world the supported features of the specified FF-A calls
+- mapping the RX/TX buffers
+- querying from secure world all the partitions information
+
+Probing fails when any of these operations fail. The FF-A bus discovery succeeds when probing is successful.
+
+When discovery fails the arm_ffa device is destroyed.
+
+The bus driver layer
+------------------------------
+
+The driver comes on top of the SMCCC layer and is implemented in drivers/firmware/arm-ffa/core.c
+
+The driver provides the following features:
+
+- Support for the 32-bit version of the following ABIs:
+
+FFA_VERSION
+FFA_ID_GET
+FFA_FEATURES
+FFA_PARTITION_INFO_GET
+FFA_RXTX_UNMAP
+FFA_RX_RELEASE
+FFA_RUN
+FFA_ERROR
+FFA_SUCCESS
+FFA_INTERRUPT
+
+- Support for the 64-bit version of the following ABIs:
+
+FFA_RXTX_MAP
+FFA_MSG_SEND_DIRECT_REQ
+FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper layers focus on exchanged data,
+the driver takes care of how to transport that to the secure world/hypervisor using FF-A.
+
+- The driver provides callbacks to be used by clients to access the FF-A bus:
+
+partition_info_get
+sync_send_receive
+rxtx_unmap
+
+- FF-A bus discovery at initcalls level (after u-boot relocation). The bus is up and running if the FF-A framework is responsive and compatible with the driver.
+
+- When EFI is enabled, unmap the RX/TX buffers at ExitBootServices() level.
+
+- When CONFIG_ARM_FFA_EFI_RUNTIME_MODE enabled, ffa_copy_runtime_data function is available for use.
+
+Using armffa command
+-----------------------------------
+
+armffa is a command showcasing how to use the FF-A driver and how to invoke its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
+
+Usage:
+
+armffa <sub-command> <arguments>
+
+sub-commands:
+
+        getpart <partition UUID>
+
+            lists the partition(s) info
+
+        ping <partition ID>
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays the arm_ffa device info
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 8b6fead351..b06b1ae481 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
 
 source "drivers/adc/Kconfig"
 
+source "drivers/firmware/arm-ffa/Kconfig"
+
 source "drivers/ata/Kconfig"
 
 source "drivers/axi/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index eba9940231..c3bfad94ac 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -110,6 +110,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..aceb61cf49
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  This driver is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In u-boot FF-A design, FF-A is considered as a discoverable bus.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  This FF-A driver takes care of all the interactions between Normal world
+	  and Secure World.
+
+	  For more details about the FF-A driver, please refer to doc/README.ffa.drv
+
+config ARM_FFA_EFI_RUNTIME_MODE
+	bool "Enable EFI runtime support for FF-A data and code"
+	depends on ARM_FFA_TRANSPORT && EFI_LOADER
+	help
+	  Allows FF-A driver data structures and code to be accessible at EFI runtime.
+	  FF-A data is copied by ffa_copy_runtime_data function.
+	  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.
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..0b9b0a61b4
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+#
+
+obj-y += arm-ffa-uclass.o core.o
+obj-$(CONFIG_ARM_FFA_EFI_RUNTIME_MODE) += efi_ffa_runtime_data_mgr.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..7d9695d289
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+UCLASS_DRIVER(ffa) = {
+	.name		= "ffa",
+	.id		= UCLASS_FFA,
+};
diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
new file mode 100644
index 0000000000..7bc90f7f66
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <arm_ffa.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/arm-smccc.h>
+
+/*
+ * This header is private. It is exclusively used by the FF-A driver
+ */
+
+/* FF-A core driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* FF-A driver version definitions */
+
+#define MAJOR_VERSION_MASK		GENMASK(30, 16)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/*
+ * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
+ */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR					= 0x60,
+	FFA_SUCCESS					= 0x61,
+	FFA_INTERRUPT				= 0x62,
+	FFA_VERSION					= 0x63,
+	FFA_FEATURES				= 0x64,
+	FFA_RX_RELEASE				= 0x65,
+	FFA_RXTX_MAP				= 0x66,
+	FFA_RXTX_UNMAP			= 0x67,
+	FFA_PARTITION_INFO_GET		= 0x68,
+	FFA_ID_GET					= 0x69,
+	FFA_RUN						= 0x6D,
+	FFA_MSG_SEND_DIRECT_REQ	= 0x6F,
+	FFA_MSG_SEND_DIRECT_RESP	= 0x70,
+
+	/* to be updated when adding new FFA IDs */
+	FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
+	FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
+};
+
+/* number of the errors supported by the FF-A specification */
+#define MAX_NUMBER_FFA_ERR 9
+
+/* container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#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
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Data structure hosting the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	u64 rxbuf; /* virtual address */
+	u64 txbuf; /* virtual address */
+	size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * This data structure contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* virtual address */
+};
+
+/**
+ * struct ffa_prvdata - the driver private data structure
+ *
+ * @dev:	The arm_ffa device under u-boot driver model
+ * @ffa_ops:	The driver operations structure
+ * @fwk_version:	FF-A framework version
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ * @invoke_ffa_fn:	The function executing the FF-A function
+ *
+ * The driver data structure hosting all resident data.
+ */
+struct ffa_prvdata {
+	struct udevice *dev;
+	struct ffa_bus_ops ffa_ops;
+	u32 fwk_version;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+	invoke_ffa_fn_t invoke_ffa_fn;
+};
+
+/**
+ * ffa_device_get - create, bind and probe the arm_ffa device
+ */
+int ffa_device_get(void);
+
+/**
+ * ffa_bus_prvdata_get - bus driver private data getter
+ */
+struct ffa_prvdata **ffa_bus_prvdata_get(void);
+
+#endif
diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
new file mode 100644
index 0000000000..41c7b96e68
--- /dev/null
+++ b/drivers/firmware/arm-ffa/core.c
@@ -0,0 +1,1344 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include "arm_ffa_prv.h"
+#include <asm/global_data.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * The device private data structure containing all the resident
+ * data read from secure world
+ */
+__ffa_runtime_data struct ffa_prvdata *ffa_priv_data;
+
+/* Error mapping declarations */
+
+__ffa_runtime_data int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	0,
+	-EOPNOTSUPP,	/* NOT_SUPPORTED */
+	-EINVAL,	/* INVALID_PARAMETERS */
+	-ENOMEM,	/* NO_MEMORY */
+	-EBUSY,		/* BUSY */
+	-EINTR,		/* INTERRUPTED */
+	-EACCES,	/* DENIED */
+	-EAGAIN,	/* RETRY */
+	-ECANCELED,	/* ABORTED */
+};
+
+struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			"",
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+			"", /* INVALID_PARAMETERS */
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"", /* DENIED */
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			"",
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			"", /* INVALID_PARAMETERS */
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"", /* DENIED */
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			"",
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+			"", /* INVALID_PARAMETERS */
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"", /* DENIED */
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			"",
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			"BUSY: RX buffer of the caller is not free",
+			"", /* INTERRUPTED */
+			"DENIED: Callee is not in a state to handle this request",
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+			{
+			"",
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"", /* DENIED */
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+			{
+			"",
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			"", /* INVALID_PARAMETERS */
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"DENIED: Caller did not have ownership of the RX buffer",
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+			{
+			"",
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			"NO_MEMORY: Not enough memory",
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"DENIED: Buffer pair already registered",
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This runtime function maps the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+__ffa_runtime int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This boot time function maps the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str || !err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/*
+ * Driver core functions
+ */
+
+/**
+ * ffa_remove_device - removes the arm_ffa device
+ * @dev:	the device to be removed
+ *
+ * This boot time function makes sure the arm_ffa device is removed
+ * No need to free the kmalloced data when the device is destroyed.
+ * It's automatically done by devm management by
+ * device_remove() -> device_free() -> devres_release_probe().
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_remove_device(struct udevice *dev)
+{
+	int ret;
+
+	if (!dev) {
+		ffa_err("no udevice found");
+		return -ENODEV;
+	}
+
+	ret = device_remove(dev, DM_REMOVE_NORMAL);
+	if (ret) {
+		ffa_err("unable to remove. err:%d\n", ret);
+		return ret;
+	}
+
+	ffa_info("device removed and freed");
+
+	ret = device_unbind(dev);
+	if (ret) {
+		ffa_err("unable to unbind. err:%d\n", ret);
+		return ret;
+	}
+
+	ffa_info("device unbound");
+
+	return 0;
+}
+
+/**
+ * ffa_device_get - create, bind and probe the arm_ffa device
+ *
+ * This boot time function makes sure the arm_ffa device is
+ * created, bound to this driver, probed and ready to use.
+ * Arm FF-A transport is implemented through a single u-boot
+ * device managing the FF-A bus (arm_ffa).
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_device_get(void)
+{
+	int ret;
+	struct udevice *dev = NULL;
+
+	ret = device_bind(dm_root(),
+			  DM_DRIVER_GET(arm_ffa),
+			  FFA_DRV_NAME,
+			  NULL,
+			  ofnode_null(),
+			  &dev);
+	if (ret)
+		return ret;
+
+	/* The FF-A bus discovery succeeds when probing is successful */
+	ret = device_probe(dev);
+	if (ret) {
+		ffa_err("arm_ffa device probing failed");
+		ffa_remove_device(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_version - FFA_VERSION handler function
+ *
+ * This is the boot time function that implements FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_version(void)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION),
+			.a1 = FFA_VERSION_1_0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	ffa_errno = (int)res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION((u32)res.a0);
+	minor = GET_FFA_MINOR_VERSION((u32)res.a0);
+
+	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
+		ffa_info("Versions are compatible ");
+
+		ffa_priv_data->fwk_version = (u32)res.a0;
+
+		return 0;
+	}
+
+	ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id - FFA_ID_GET handler function
+ *
+ * This is the boot time function that implements FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			.a1 = 0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		ffa_info("endpoint ID is %u", ffa_priv_data->id);
+
+		return 0;
+	}
+
+	ffa_errno = (int)res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * This boot time function sets the minimum number of pages
+ *  in each of the RX/TX buffers in the private data structure
+ *
+ * Return:
+ *
+ * buf_4k_pages points to the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
+{
+	if (!ffa_priv_data)
+		return -EINVAL;
+
+	switch (prop_field) {
+	case RXTX_4K:
+		ffa_priv_data->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		ffa_priv_data->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		ffa_priv_data->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		ffa_err("RX/TX buffer size not supported");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ *
+ * This is the boot time function that implements FFA_FEATURES FF-A function
+ * to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt((u32)res.a2);
+
+	ffa_errno = (int)res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers - frees the RX/TX buffers
+ *
+ * This is the boot time function used to free the RX/TX buffers
+ *
+ */
+static void ffa_free_rxtx_buffers(void)
+{
+	ffa_info("Freeing RX/TX buffers");
+
+	if (ffa_priv_data->pair.rxbuf) {
+		free((void *)ffa_priv_data->pair.rxbuf);
+		ffa_priv_data->pair.rxbuf = 0;
+	}
+
+	if (ffa_priv_data->pair.txbuf) {
+		free((void *)ffa_priv_data->pair.txbuf);
+		ffa_priv_data->pair.txbuf = 0;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
+ *
+ * This is the boot time function used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(void)
+{
+	u64 bytes;
+
+	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
+		 ffa_priv_data->pair.rxtx_min_pages);
+
+	bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
+
+	/* RX/TX buffers addresses should be PAGE_SIZE aligned */
+
+	ffa_priv_data->pair.rxbuf = (u64)memalign(PAGE_SIZE, bytes);
+	if (!ffa_priv_data->pair.rxbuf) {
+		ffa_err("failure to allocate RX buffer");
+		return -ENOBUFS;
+	}
+
+	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
+
+	ffa_priv_data->pair.txbuf = (u64)memalign(PAGE_SIZE, bytes);
+	if (!ffa_priv_data->pair.txbuf) {
+		free((void *)ffa_priv_data->pair.rxbuf);
+		ffa_priv_data->pair.rxbuf = 0;
+		ffa_err("failure to allocate the TX buffer");
+		return -ENOBUFS;
+	}
+
+	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
+
+	/*
+	 * make sure the buffers are cleared before use
+	 */
+	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
+	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
+ *
+ * This is the boot time function that implements FFA_RXTX_MAP FF-A function
+ * to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers(void)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ret = ffa_alloc_rxtx_buffers();
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 *no need to convert from virtual to physical
+	 */
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = ffa_priv_data->pair.txbuf,
+			.a2 = ffa_priv_data->pair.rxbuf,
+			.a3 = ffa_priv_data->pair.rxtx_min_pages,
+			.a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_info("RX/TX buffers mapped");
+		return 0;
+	}
+
+	ffa_errno = (int)res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers();
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
+ *
+ * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_unmap_rxtx_buffers(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id),
+			.a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers();
+		return 0;
+	}
+
+	ffa_errno = (int)res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
+ *
+ * This is the boot time function that invokes FFA_RX_RELEASE FF-A function
+ * to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			.a1 = 0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = (int)res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical - checks whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * This is a boot time function used by ffa_read_partitions_info to search
+ * for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+int ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+			   const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return (!memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid)));
+}
+
+/**
+ * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
+ *							and saves it in the private structure
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * This is the boot time function that reads the partitions information
+ * returned by the FFA_PARTITION_INFO_GET and saves it in the private
+ * data structure.
+ *
+ * Return:
+ *
+ * The private data structure is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
+{
+	if (!count) {
+		ffa_err("no partition detected");
+		return -ENODATA;
+	}
+
+	ffa_info("Reading partitions data from the RX buffer");
+
+	if (!part_uuid) {
+		/*
+		 * querying information of all partitions
+		 */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			ffa_err("partitions data size exceeds the RX buffer size:");
+			ffa_err("    sizes in bytes: data %llu , RX buffer %llu ",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		ffa_priv_data->partitions.descs = (struct ffa_partition_desc *)
+			devm_kmalloc(ffa_priv_data->dev, data_bytes, __GFP_ZERO);
+		if (!ffa_priv_data->partitions.descs) {
+			ffa_err("cannot  allocate partitions data buffer");
+			return -ENOMEM;
+		}
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			ffa_priv_data->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			ffa_info("Partition ID %x : info cached",
+				 ffa_priv_data->partitions.descs[desc_idx].info.id);
+		}
+
+		ffa_priv_data->partitions.count = count;
+
+		ffa_info("%d partition(s) found and cached", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
+
+		/*
+		 * search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/*
+			 * search the current ID in the cached partitions
+			 */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < ffa_priv_data->partitions.count;
+			     cached_desc_idx++) {
+				/*
+				 * save the UUID
+				 */
+				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
+ *
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * This is the boot time function that executes the FFA_PARTITION_INFO_GET
+ * to query the partitions data. Then, it calls ffa_read_partitions_info
+ * to save the data in the private data structure.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			.a5 = 0,
+			.a6 = 0,
+			.a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
+			if (ret) {
+				ffa_err("failed to read partition(s) data , error (%d)", ret);
+				ffa_release_rx_buffer();
+				return -EINVAL;
+			}
+		}
+
+		/*
+		 * return the SP count (when querying using a UUID)
+		 */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer();
+
+		return ret;
+	}
+
+	ffa_errno = (int)res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
+ *
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@uuid_str: pointer to the UUID string
+ *	@parts_size: pointer to the variable that contains the number of partitions
+ *			 The variable will be set by the driver
+ *	@buffer: NULL
+ *
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@uuid_str: pointer to the UUID string
+ *	@parts_size: pointer to the size of the SPs information buffer in bytes
+ *	@buffer: pointer to SPs information buffer
+ *		(allocated by the client).
+ *		The buffer will be filled by the driver
+ *
+ * This is the boot time function that queries the secure partition data from
+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * When invoked through a client request, ffa_get_partitions_info should be
+ * called twice. First call is to get from the driver the number of secure
+ * partitions (SPs) associated to a particular UUID.
+ * Then, the caller (client) allocates the buffer to host the SPs data and
+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
+ * buffer.
+ *
+ * To achieve the mechanism described above, ffa_get_partitions_info uses the
+ * following functions:
+ *		ffa_read_partitions_info
+ *		ffa_query_partitions_info
+ *
+ * Return:
+ *
+ * @parts_size: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer size, the buffer will be
+ * filled by the driver.
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+static int ffa_get_partitions_info(const char *uuid_str,
+				   u32 *parts_size, struct ffa_partition_info *buffer)
+{
+	/*
+	 * fill_data:
+	 * 0: return the SP count
+	 * 1: fill SP data and return it to the caller
+	 * -1: undefined mode
+	 */
+	int fill_data = -1;
+	u32 desc_idx, client_desc_idx;
+	struct ffa_partition_uuid part_uuid = {0};
+	u32 client_desc_max_cnt;
+	u32 parts_found = 0;
+
+	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
+		ffa_err("no partition installed");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		ffa_err("no UUID provided");
+		return -EINVAL;
+	}
+
+	if (!parts_size) {
+		ffa_err("no size/count provided");
+		return -EINVAL;
+	}
+
+	if (be_uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		ffa_err("invalid UUID");
+		return -EINVAL;
+	}
+
+	if (!buffer) {
+		/* Mode 1: getting the number of secure partitions */
+
+		fill_data = 0;
+
+		ffa_info("Preparing for checking partitions count");
+
+	} else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
+		   !(*parts_size % sizeof(struct ffa_partition_info))) {
+		/* Mode 2: retrieving the partitions information */
+
+		fill_data = 1;
+
+		client_desc_idx = 0;
+
+		/*
+		 * number of empty descriptors preallocated by the caller
+		 */
+		client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
+
+		ffa_info("Preparing for filling partitions info");
+
+	} else {
+		ffa_err("invalid function arguments provided");
+		return -EINVAL;
+	}
+
+	ffa_info("Searching partitions using the provided UUID");
+
+	/*
+	 * search in the cached partitions
+	 */
+	for (desc_idx = 0;
+	     desc_idx < ffa_priv_data->partitions.count;
+	     desc_idx++) {
+		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
+					   &part_uuid)) {
+			ffa_info("Partition ID %x matches the provided UUID",
+				 ffa_priv_data->partitions.descs[desc_idx].info.id);
+
+			parts_found++;
+
+			if (fill_data) {
+				/*
+				 * trying to fill the partition info in the input buffer
+				 */
+
+				if (client_desc_idx < client_desc_max_cnt) {
+					buffer[client_desc_idx++] =
+						ffa_priv_data->partitions.descs[desc_idx].info;
+					continue;
+				}
+
+				ffa_err("failed to fill the current descriptor client buffer full");
+				return -ENOBUFS;
+			}
+		}
+	}
+
+	if (!parts_found) {
+		int ret;
+
+		ffa_info("No partition found. Querying framework ...");
+
+		ret = ffa_query_partitions_info(&part_uuid, &parts_found);
+
+		if (ret == 0) {
+			if (!fill_data) {
+				*parts_size = parts_found;
+
+				ffa_info("Number of partition(s) found matching the UUID: %d",
+					 parts_found);
+			} else {
+				/*
+				 * If SPs data detected, they are already in the private data
+				 * structure, retry searching SP data again to return them
+				 *  to the caller
+				 */
+				if (parts_found)
+					ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
+				else
+					ret = -ENODATA;
+			}
+		}
+
+		return ret;
+	}
+
+	/* partition(s) found */
+	if (!fill_data)
+		*parts_size = parts_found;
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info - Queries and saves all secure partitions data
+ *
+ * This is a boot time function that invokes FFA_PARTITION_INFO_GET FF-A
+ * function to query from secure world all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in the
+ * resident private data structure and we keep the UUID field empty
+ * (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * This function is called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(void)
+{
+	return ffa_query_partitions_info(NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ *
+ * This is the runtime function that implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int __ffa_runtime ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
+		return -EINVAL;
+
+	/* No partition installed */
+	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
+		return -ENODEV;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ),
+			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP)) {
+		/*
+		 * Message sent with response
+		 * extract the return data
+		 */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = (int)res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * __arm_ffa_fn_smc - 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 low level SMC assembly function
+ *
+ * Return: void
+ */
+void __ffa_runtime __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * ffa_set_smc_conduit - Set the SMC conduit
+ *
+ * This boot time function selects the SMC conduit by setting the driver invoke function
+ * to SMC assembly function
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_smc_conduit(void)
+{
+	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
+
+	if (!ffa_priv_data->invoke_ffa_fn) {
+		ffa_err("failure to set the invoke function");
+		return -EINVAL;
+	}
+
+	ffa_info("Conduit is SMC");
+
+	return 0;
+}
+
+/**
+ * ffa_set_bus_ops - Set the bus driver operations
+ *
+ * Setting the driver callbacks.
+ *
+ */
+static void ffa_set_bus_ops(void)
+{
+	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
+	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
+	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
+}
+
+/**
+ * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
+ * @dev:	the arm_ffa device
+ *
+ * This boot time function creates the main data structure embedding all the driver data.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_prvdata(struct udevice *dev)
+{
+	if (!dev) {
+		ffa_err("no udevice found");
+		return -ENODEV;
+	}
+
+	/* The device is registered with the DM. Let's create the driver main data structure*/
+
+	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
+	if (!ffa_priv_data) {
+		ffa_err("can not allocate the driver main data structure");
+		return -ENOMEM;
+	}
+
+	ffa_priv_data->dev = dev;
+
+	return 0;
+}
+
+/**
+ * ffa_probe - The driver probe function
+ * @dev:	the arm_ffa device
+ *
+ * Probing is done at boot time and triggered by the uclass device discovery.
+ * At probe level the following actions are done:
+ *	- setting the conduit
+ *	- querying the FF-A framework version
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in the resident private data structure.
+ *
+ * The probe will fail if either FF-A framework is not detected or the
+ * FF-A requests are not behaving correctly. This ensures that the
+ * driver is not installed and its operations are not exported to the clients.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = ffa_alloc_prvdata(dev);
+	if (ret != 0)
+		return ret;
+
+	ffa_set_bus_ops();
+
+	ret = ffa_set_smc_conduit();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_version();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_endpoint_id();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_cache_partitions_info();
+	if (ret != 0) {
+		ffa_free_rxtx_buffers();
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_remove - The driver remove function
+ * @dev:	the arm_ffa device
+ * When the device is about to be removed ,  unmap the RX/TX buffers and free the memory
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_remove(struct udevice *dev)
+{
+	ffa_info("removing the device");
+
+	ffa_unmap_rxtx_buffers();
+
+	if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
+		ffa_free_rxtx_buffers();
+
+	return 0;
+}
+
+/**
+ * ffa_unbind - The driver unbind function
+ * @dev:	the arm_ffa device
+ * After the device is removed and memory freed the device is unbound
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_unbind(struct udevice *dev)
+{
+	ffa_info("unbinding the device , private data already released");
+
+	ffa_priv_data = NULL;
+
+	return 0;
+}
+
+/**
+ * ffa_bus_ops_get - bus driver operations getter
+ *
+ * Return:
+ * This runtime function returns a pointer to the driver operations structure
+ */
+const struct ffa_bus_ops * __ffa_runtime ffa_bus_ops_get(void)
+{
+	return &ffa_priv_data->ffa_ops;
+}
+
+/**
+ * ffa_bus_prvdata_get - bus driver private data getter
+ *
+ * Return:
+ * This boot time function returns a pointer to the main private data structure
+ */
+struct ffa_prvdata **ffa_bus_prvdata_get(void)
+{
+	return &ffa_priv_data;
+}
+
+/**
+ * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
+ *
+ * This boot time function makes sure the FF-A bus is discoverable.
+ * Then, the arm_ffa device is probed and 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.
+ * All FF-A clients should use the arm_ffa device to use the FF-A transport.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_bus_discover(void)
+{
+	int ret = 0;
+
+	if (!ffa_priv_data)
+		ret = ffa_device_get();
+
+	return ret;
+}
+
+/**
+ * Declaring the arm_ffa driver under UCLASS_FFA
+ */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.probe		= ffa_probe,
+	.remove		= ffa_remove,
+	.unbind		= ffa_unbind,
+};
diff --git a/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c b/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
new file mode 100644
index 0000000000..c76cf2147b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include "arm_ffa_prv.h"
+
+/**
+ * ffa_copy_runtime_data - copy the private data structure  to the runtime area
+ *
+ * This boot time function copies the arm_ffa driver data structures including
+ *  partitions data to the EFI runtime data section.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+efi_status_t ffa_copy_runtime_data(void)
+{
+	efi_status_t efi_ret;
+	efi_uintn_t prvdata_pages;
+	efi_uintn_t descs_pages;
+	struct ffa_prvdata **prvdata = NULL; /* Pointer to the current structure */
+	struct ffa_prvdata *runtime_prvdata = NULL; /* Pointer to the structure runtime copy */
+	u64 runtime_descs = 0;
+
+	prvdata = ffa_bus_prvdata_get();
+
+	printf("INFO: EFI: FFA: prv data area at 0x%llx\n", (u64)prvdata);
+
+	/* allocate private data runtime area */
+
+	prvdata_pages = efi_size_in_pages(sizeof(struct ffa_prvdata));
+	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				     EFI_RUNTIME_SERVICES_DATA,
+				     prvdata_pages,
+				     (u64 *)&runtime_prvdata);
+
+	if (efi_ret != EFI_SUCCESS) {
+		printf("ERROR: EFI: FFA: allocating runtime data (err: 0x%lx, addr 0x%llx)\n",
+		       efi_ret, (u64)runtime_prvdata);
+
+		return efi_ret;
+	}
+
+	printf("INFO: EFI: FFA: runtime data area at 0x%llx\n", (u64)runtime_prvdata);
+
+	if (!runtime_prvdata)
+		return EFI_INVALID_PARAMETER;
+
+	/* allocate the partition data runtime area */
+
+	descs_pages = efi_size_in_pages((*prvdata)->partitions.count *
+					sizeof(struct ffa_partition_desc));
+	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				     EFI_RUNTIME_SERVICES_DATA,
+				     descs_pages,
+				     &runtime_descs);
+
+	if (efi_ret != EFI_SUCCESS) {
+		printf("ERROR: EFI: FFA: allocating runtime SPs data (err: 0x%lx, addr 0x%llx)\n",
+		       efi_ret, runtime_descs);
+
+		efi_free_pages((u64)runtime_prvdata, prvdata_pages);
+
+		return efi_ret;
+	}
+
+	printf("INFO: EFI: FFA: SPs runtime area at 0x%llx\n", (u64)runtime_descs);
+
+	if (!runtime_descs)
+		return EFI_INVALID_PARAMETER;
+
+	*runtime_prvdata = **prvdata;
+
+	runtime_prvdata->dev = NULL;
+	runtime_prvdata->ffa_ops.partition_info_get = NULL;
+	runtime_prvdata->ffa_ops.rxtx_unmap = NULL;
+	runtime_prvdata->partitions.descs = (struct ffa_partition_desc *)runtime_descs;
+	runtime_prvdata->pair.rxbuf = 0;
+	runtime_prvdata->pair.txbuf = 0;
+
+	/*
+	 * Update the private data structure pointer in the driver
+	 * no need to free the old structure. devm takes care of that
+	 */
+	*prvdata = runtime_prvdata;
+
+	printf("INFO: EFI: FFA: runtime prv data now at 0x%llx , SPs count %d\n",
+	       (u64)*prvdata, (*prvdata)->partitions.count);
+
+	return 0;
+}
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..f17b100497
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * Macros for displaying logs
+ */
+
+#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
+#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct  __packed ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct __packed ffa_send_direct_data {
+	unsigned long data0; /* w3/x3 */
+	unsigned long data1; /* w4/x4 */
+	unsigned long data2; /* w5/x5 */
+	unsigned long data3; /* w6/x6 */
+	unsigned long data4; /* w7/x7 */
+};
+
+#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
+
+#include <efi_loader.h>
+
+/*
+ *  __ffa_runtime - controls whether functions are
+ * available after calling the EFI ExitBootServices service.
+ * Functions tagged with these keywords are resident (available at boot time and
+ * at runtime)
+ */
+
+#define __ffa_runtime_data __efi_runtime_data
+#define __ffa_runtime __efi_runtime
+
+#else
+
+/*
+ *  The FF-A driver is independent from EFI
+ */
+
+#define __ffa_runtime_data
+#define __ffa_runtime
+
+#endif
+
+/**
+ * struct ffa_bus_ops - The driver operations structure
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(const char *uuid_str,
+				  u32 *parts_size, struct ffa_partition_info *buffer);
+	int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg);
+	int (*rxtx_unmap)(void);
+};
+
+/**
+ * The device driver and the Uclass driver public functions
+ */
+
+/**
+ * ffa_bus_ops_get - driver operations getter
+ */
+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
+ */
+int ffa_bus_discover(void);
+
+#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
+
+/**
+ * ffa_copy_runtime_data - copy the private data structure and the SPs data to the runtime area
+ */
+efi_status_t ffa_copy_runtime_data(void);
+
+#endif
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index a432e43871..5dd698b7a9 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,9 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -55,6 +58,7 @@ enum uclass_id {
 	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
 	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 6f7333638a..af0b0f3db1 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -3,6 +3,9 @@
  * EFI application boot time services
  *
  * Copyright (c) 2016 Alexander Graf
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -23,6 +26,10 @@
 #include <asm/setjmp.h>
 #include <linux/libfdt_env.h>
 
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+#include <arm_ffa.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Task priority level */
@@ -2178,6 +2185,14 @@ 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)
+		/* 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");
+		else
+			debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
+#endif
+
 	/* Patch out unsupported runtime function */
 	efi_runtime_detach();
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v5 05/10] arm_ffa: introduce armffa command
  2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                     ` (3 preceding siblings ...)
  2022-09-26 14:08                                   ` [PATCH v5 04/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
@ 2022-09-26 14:08                                   ` Abdellatif El Khlifi
  2022-09-26 14:08                                   ` [PATCH v5 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
                                                     ` (5 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 14:08 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong

Provide armffa command showcasing the use of the FF-A driver

The armffa command allows to query secure partitions data from
the secure world and exchanging messages with the partitions.

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>
---

Changelog:
===============

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

 MAINTAINERS                      |   1 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   2 +
 cmd/armffa.c                     | 242 +++++++++++++++++++++++++++++++
 drivers/firmware/arm-ffa/Kconfig |   1 +
 5 files changed, 256 insertions(+)
 create mode 100644 cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 02b84d5074..fd3b2c4263 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -251,6 +251,7 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+F:	cmd/armffa.c
 F:	doc/README.ffa.drv
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 0e0be94f41..013d4c3da7 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -912,6 +912,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the Arm FF-A driver
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index 6e87522b62..979c6d59df 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,8 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
 obj-$(CONFIG_CMD_AES) += aes.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..9b56e8a830
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <arm_ffa.h>
+#include <asm/io.h>
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+
+/**
+ * do_ffa_get_singular_partition_info - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver partition_info_get operation
+ * to retrieve the data.
+ * The input UUID string is expected to be in big endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_get_singular_partition_info(struct cmd_tbl *cmdtp, int flag, int argc,
+					      char *const argv[])
+{
+	u32 count = 0, size = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	/* Mode 1: getting the number of secure partitions */
+	ret = ffa_bus_ops_get()->partition_info_get(argv[0], &count, NULL);
+	if (ret != 0) {
+		ffa_err("Failure in querying partitions count (error code: %d)", ret);
+		return ret;
+	}
+
+	if (!count) {
+		ffa_info("No secure partition found");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with ffa_partition_info structs
+	 */
+
+	ffa_info("Pre-allocating %d partition(s) info structures", count);
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	size = count * sizeof(struct ffa_partition_info);
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+
+	ret = ffa_bus_ops_get()->partition_info_get(argv[0], &size, parts_info);
+	if (ret != 0) {
+		ffa_err("Failure in querying partition(s) info (error code: %d)", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * SPs found , show the partition information
+	 */
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		ffa_info("Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x",
+			 parts_info[info_idx].id,
+			 parts_info[info_idx].exec_ctxt,
+			 parts_info[info_idx].properties);
+	}
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * do_ffa_msg_send_direct_req - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function sends data to the secure partition which the ID is provided
+ * as an argument. The function uses the arm_ffa driver sync_send_receive operation
+ * to send data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int  do_ffa_msg_send_direct_req(struct cmd_tbl *cmdtp, int flag, int argc,
+				char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	errno = 0;
+	part_id = strtoul(argv[0], NULL, 16);
+
+	if (errno) {
+		ffa_err("Invalid partition ID");
+		return -EINVAL;
+	}
+
+	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
+	if (ret == 0) {
+		u8 cnt;
+
+		ffa_info("SP response:\n[LSB]");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			ffa_info("0x%llx", ((u64 *)&msg)[cnt]);
+	} else {
+		ffa_err("Sending direct request error (%d)", ret);
+	}
+
+	return ret;
+}
+
+/**
+ *do_ffa_dev_list - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the devices belonging to the UCLASS_FFA
+ * class. Currently, one device is expected to show up: the arm_ffa device
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_dev_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev = NULL;
+	int i, ret;
+
+	ffa_info("arm_ffa uclass entries:");
+
+	for (i = 0, ret = uclass_first_device(UCLASS_FFA, &dev);
+	     dev;
+	     ret = uclass_next_device(&dev), i++) {
+		if (ret)
+			break;
+
+		ffa_info("entry %d - instance %08x, ops %08x, plat %08x",
+			 i,
+			 (u32)map_to_sysmem(dev),
+			 (u32)map_to_sysmem(dev->driver->ops),
+			 (u32)map_to_sysmem(dev_get_plat(dev)));
+	}
+
+	return cmd_process_error(cmdtp, ret);
+}
+
+static struct cmd_tbl armffa_commands[] = {
+	U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_get_singular_partition_info, "", ""),
+	U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_msg_send_direct_req, "", ""),
+	U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_dev_list, "", ""),
+};
+
+/**
+ * do_armffa - the armffa command main function
+ * @cmdtp:	Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function identifies which armffa subcommand to run.
+ * Then, it makes sure the arm_ffa device is probed and
+ * ready for use.
+ * Then, it runs the subcommand.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct cmd_tbl *armffa_cmd;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
+
+	argc -= 2;
+	argv += 2;
+
+	if (!armffa_cmd || argc > armffa_cmd->maxargs)
+		return CMD_RET_USAGE;
+
+	ret = ffa_bus_discover();
+	if (ret != 0)
+		return cmd_process_error(cmdtp, ret);
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
+
+	return cmd_process_error(armffa_cmd, ret);
+}
+
+U_BOOT_CMD(armffa, 4, 1, do_armffa,
+	   "Arm FF-A operations test command",
+	   "getpart <partition UUID>\n"
+	   "	 - lists the partition(s) info\n"
+	   "ping <partition ID>\n"
+	   "	 - sends a data pattern to the specified partition\n"
+	   "devlist\n"
+	   "	 - displays the arm_ffa device info\n");
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index aceb61cf49..40b467b0a5 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -4,6 +4,7 @@ config ARM_FFA_TRANSPORT
 	bool "Enable Arm Firmware Framework for Armv8-A driver"
 	depends on DM && ARM64
 	select ARM_SMCCC
+	select CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v5 06/10] arm_ffa: introduce the FF-A Sandbox driver
  2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                     ` (4 preceding siblings ...)
  2022-09-26 14:08                                   ` [PATCH v5 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2022-09-26 14:08                                   ` Abdellatif El Khlifi
  2022-09-26 14:08                                   ` [PATCH v5 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                     ` (4 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 14:08 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong

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>
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>

---

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 fd3b2c4263..6f01002e34 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -255,6 +255,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 8c99faddfd..7f1eae65df 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -776,7 +776,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 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 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 af0b0f3db1..d404343a7d 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())
 			debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n");
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v5 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                     ` (5 preceding siblings ...)
  2022-09-26 14:08                                   ` [PATCH v5 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
@ 2022-09-26 14:08                                   ` Abdellatif El Khlifi
  2022-09-26 14:08                                   ` [PATCH v5 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                     ` (3 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 14:08 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong

Add functional test cases for the FF-A core driver

These tests rely on the FF-A Sandbox driver which helps in
 inspecting the FF-A core driver.

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>

---

Changelog:
===============

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

v1: introduce sandbox tests

 MAINTAINERS      |   1 +
 test/dm/Makefile |   2 +
 test/dm/ffa.c    | 394 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 397 insertions(+)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 6f01002e34..8c0dfff5f8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -256,6 +256,7 @@ F:	doc/README.ffa.drv
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/sandbox_arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 7543df8823..e5a791768e 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# (C) Copyright 2022 ARM Limited
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -81,6 +82,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_SANDBOX_FFA) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..052d5fc3f4
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <dm.h>
+#include <dm/test.h>
+#include "../../drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h"
+#include <sandbox_arm_ffa.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Macros */
+
+#define LOG_MSG_SZ (100)
+#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
+
+/* Functional tests for the UCLASS_FFA */
+
+static int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
+{
+	char cmd[LOG_CMD_SZ] = {0};
+
+	console_record_reset();
+
+	snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
+	run_command(cmd, 0);
+
+	ut_assert_console_end();
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_fwk_version(struct ffa_prvdata *prvdata, struct sandbox_ffa_prvdata *sdx_prvdata,
+			     struct unit_test_state *uts)
+{
+	if (prvdata->fwk_version != sdx_prvdata->fwk_version) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: framework version: core = 0x%x , sandbox  = 0x%x", __func__,
+			 prvdata->fwk_version,
+			sdx_prvdata->fwk_version);
+
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_endpoint_id(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (prvdata->id) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: endpoint id: core = 0x%x", __func__, prvdata->id);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_core_dev(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->dev) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: core device NULL", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_sandbox_dev(struct sandbox_ffa_prvdata *sdx_prvdata, struct unit_test_state *uts)
+{
+	if (!sdx_prvdata->dev) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: sandbox device NULL", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_rxtxbuf(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->pair.rxbuf && prvdata->pair.txbuf) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = 0x%llx txbuf = 0x%llx", __func__,
+			 prvdata->pair.rxbuf,
+			 prvdata->pair.txbuf);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_features(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	if (prvdata->pair.rxtx_min_pages != RXTX_4K &&
+	    prvdata->pair.rxtx_min_pages != RXTX_16K &&
+	    prvdata->pair.rxtx_min_pages != RXTX_64K) {
+		snprintf(msg,
+			 LOG_MSG_SZ,
+			 "[%s]: Error: FFA_RXTX_MAP features = 0x%lx",
+			 __func__,
+			 prvdata->pair.rxtx_min_pages);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+	{
+		if (rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	case FFA_RXTX_UNMAP:
+	{
+		if (!rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	default:
+		return CMD_RET_FAILURE;
+	}
+
+	snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__,
+		 (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP"));
+	dm_test_ffa_log(uts, msg);
+
+	return CMD_RET_FAILURE;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	if (rxbuf_owned) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg = {0};
+	u8 cnt;
+
+	ut_assertok(ffa_bus_ops_get()->sync_send_receive(part_id, &msg));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_assertok(((u64 *)&msg)[cnt] != 0xffffffffffffffff);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct sandbox_ffa_prvdata *sdx_prvdata,
+				     struct unit_test_state *uts)
+{
+	u32 count = 0, size = 0;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx, exp_info_idx;
+	int ret;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &count, NULL);
+	/* make sure partitions are detected */
+	ut_assertok(ret != 0);
+	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	ut_assertok(!parts_info);
+
+	size = count * sizeof(struct ffa_partition_info);
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &size, parts_info);
+	if (ret != 0) {
+		free(parts_info);
+		ut_assertok(ret != 0);
+	}
+
+	/*
+	 * SPs found , verify the partitions information
+	 */
+
+	ret = CMD_RET_FAILURE;
+
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		for (exp_info_idx = 0;
+		     exp_info_idx < sdx_prvdata->partitions.count;
+		     exp_info_idx++) {
+			if (parts_info[info_idx].id ==
+			   sdx_prvdata->partitions.descs[exp_info_idx].info.id) {
+				ret = memcmp(&parts_info[info_idx],
+					     &sdx_prvdata->partitions.descs[exp_info_idx]
+					     .info,
+					     sizeof(struct ffa_partition_info));
+				if (ret)
+					free(parts_info);
+				ut_assertok(ret != 0);
+				/* send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
+			}
+			ret = CMD_RET_SUCCESS;
+		}
+	}
+
+	free(parts_info);
+
+	/* Verify  expected partitions found in the emulated secure world*/
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+	struct ffa_sandbox_data func_data = {0};
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	int ret;
+
+	/*  test probing FF-A devices */
+	ut_assertok(ffa_bus_discover());
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+
+	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
+
+	/* make sure private data pointers are retrieved */
+	ut_assertok(prvdata == 0);
+	ut_assertok(sdx_prvdata == 0);
+
+	/* make sure dev devices created */
+	ut_assertok(check_core_dev(prvdata, uts));
+	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
+
+	/* test FFA_VERSION */
+	ut_assertok(check_fwk_version(prvdata, sdx_prvdata, uts));
+
+	/* test FFA_ID_GET */
+	ut_assertok(check_endpoint_id(prvdata, uts));
+
+	/* test FFA_FEATURES */
+	ut_assertok(check_features(prvdata, uts));
+
+	/*  test core RX/TX buffers */
+	ut_assertok(check_rxtxbuf(prvdata, uts));
+
+	/* test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_MAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc1_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc2_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* test FFA_RXTX_UNMAP */
+	ut_assertok(ffa_bus_ops_get()->rxtx_unmap());
+
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_UNMAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+	struct ffa_sandbox_data func_data = {0};
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	u32 count = 0;
+	u16 part_id = 0;
+
+	/*  test probing FF-A devices */
+	ut_assertok(ffa_bus_discover());
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+
+	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
+
+	/* make sure private data pointers are retrieved */
+	ut_assertok(prvdata == 0);
+	ut_assertok(sdx_prvdata == 0);
+
+	/* make sure dev devices created */
+	ut_assertok(check_core_dev(prvdata, uts));
+	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
+
+	/* query partitions count using  invalid arguments  */
+	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, NULL, NULL);
+	ut_assertok(ret != -EINVAL);
+
+	/* query partitions count using an invalid UUID  string */
+	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid_str, &count, NULL);
+	ut_assertok(ret != -EINVAL);
+
+	/* query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, &count, NULL);
+	ut_assertok(count != 0);
+
+	/* query partitions count using a valid UUID  */
+	count = 0;
+	ret = ffa_bus_ops_get()->partition_info_get(valid_svc_uuid, &count, NULL);
+	/* make sure partitions are detected */
+	ut_assertok(ret != 0);
+	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
+
+	/* send data to an invalid partition */
+	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
+	ut_assertok(ret != -EINVAL);
+
+	/* send data to a valid partition */
+	part_id = prvdata->partitions.descs[0].info.id;
+	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
+	ut_assertok(ret != 0);
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v5 08/10] arm_ffa: introduce armffa command Sandbox test
  2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                     ` (6 preceding siblings ...)
  2022-09-26 14:08                                   ` [PATCH v5 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2022-09-26 14:08                                   ` Abdellatif El Khlifi
  2022-09-26 14:08                                   ` [PATCH v5 09/10] arm_ffa: introduce FF-A MM communication Abdellatif El Khlifi
                                                     ` (2 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 14:08 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong

Add Sandbox test for the armffa command

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>

---

Changelog:
===============

v4: drop use of helper APIs

v1: introduce armffa command sandbox test

 MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 40 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 43 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 8c0dfff5f8..8ed94da4c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -256,6 +256,7 @@ F:	doc/README.ffa.drv
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/sandbox_arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index c331757425..19e9d0a995 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# (C) Copyright 2022 ARM Limited
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -13,3 +14,4 @@ obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
 obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PWM) += pwm.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_SANDBOX_FFA) += armffa.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..531f82066e
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <sandbox_arm_ffa.h>
+#include <string.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define PING_CMD_SIZE 19
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	char ping_cmd[PING_CMD_SIZE] = {0};
+
+	ut_assertok(ffa_bus_discover());
+
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	snprintf(ping_cmd, PING_CMD_SIZE, "armffa ping 0x%x", SANDBOX_SP1_ID);
+
+	/* armffa ping <ID> */
+	ut_assertok(run_command(ping_cmd, 0));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v5 09/10] arm_ffa: introduce FF-A MM communication
  2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                     ` (7 preceding siblings ...)
  2022-09-26 14:08                                   ` [PATCH v5 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2022-09-26 14:08                                   ` Abdellatif El Khlifi
  2022-09-29  9:32                                     ` Ilias Apalodimas
  2022-09-26 14:08                                   ` [PATCH v5 10/10] arm_ffa: corstone1000: enable EFI " Abdellatif El Khlifi
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 14:08 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong, Gowtham Suresh Kumar

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

FF-A driver private data is copied to EFI runtime section at
ExitBootServices(). This garantees secure world partitions data are
available at EFI runtime level.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>

---

Changelog:
===============

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

 arch/arm/cpu/armv8/cache.S        |  19 +++
 arch/arm/cpu/armv8/cache_v8.c     |   6 +-
 include/mm_communication.h        |   9 +-
 lib/efi_loader/Kconfig            |  14 +-
 lib/efi_loader/efi_boottime.c     |   7 +
 lib/efi_loader/efi_variable_tee.c | 263 +++++++++++++++++++++++++++++-
 6 files changed, 309 insertions(+), 9 deletions(-)

diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S
index d1cee23437..91b7c73c17 100644
--- a/arch/arm/cpu/armv8/cache.S
+++ b/arch/arm/cpu/armv8/cache.S
@@ -3,6 +3,9 @@
  * (C) Copyright 2013
  * David Feng <fenghua@phytium.com.cn>
  *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ *
  * This file is based on sample code from ARMv8 ARM.
  */
 
@@ -21,7 +24,11 @@
  * x1: 0 clean & invalidate, 1 invalidate only
  * x2~x9: clobbered
  */
+#ifdef CONFIG_EFI_LOADER
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_dcache_level, "ax"
+#endif
 ENTRY(__asm_dcache_level)
 	lsl	x12, x0, #1
 	msr	csselr_el1, x12		/* select cache level */
@@ -65,7 +72,11 @@ ENDPROC(__asm_dcache_level)
  *
  * flush or invalidate all data cache by SET/WAY.
  */
+#ifdef CONFIG_EFI_LOADER
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_dcache_all, "ax"
+#endif
 ENTRY(__asm_dcache_all)
 	mov	x1, x0
 	dsb	sy
@@ -109,7 +120,11 @@ ENTRY(__asm_flush_dcache_all)
 ENDPROC(__asm_flush_dcache_all)
 .popsection
 
+#ifdef CONFIG_EFI_LOADER
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_invalidate_dcache_all, "ax"
+#endif
 ENTRY(__asm_invalidate_dcache_all)
 	mov	x0, #0x1
 	b	__asm_dcache_all
@@ -182,7 +197,11 @@ ENTRY(__asm_invalidate_icache_all)
 ENDPROC(__asm_invalidate_icache_all)
 .popsection
 
+#ifdef CONFIG_EFI_LOADER
+.pushsection .text.efi_runtime, "ax"
+#else
 .pushsection .text.__asm_invalidate_l3_dcache, "ax"
+#endif
 WEAK(__asm_invalidate_l3_dcache)
 	mov	x0, #0			/* return status as success */
 	ret
diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index e4736e5643..45f57372c2 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -5,10 +5,14 @@
  *
  * (C) Copyright 2016
  * Alexander Graf <agraf@suse.de>
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
 #include <cpu_func.h>
+#include <efi_loader.h>
 #include <hang.h>
 #include <log.h>
 #include <asm/cache.h>
@@ -445,7 +449,7 @@ __weak void mmu_setup(void)
 /*
  * Performs a invalidation of the entire data cache at all levels
  */
-void invalidate_dcache_all(void)
+void __efi_runtime invalidate_dcache_all(void)
 {
 	__asm_invalidate_dcache_all();
 	__asm_invalidate_l3_dcache();
diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..fe9104c56d 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,8 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +15,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
@@ -43,7 +48,7 @@
  * To avoid confusion in interpreting frames, the communication buffer should
  * always begin with efi_mm_communicate_header.
  */
-struct __packed efi_mm_communicate_header {
+struct efi_mm_communicate_header {
 	efi_guid_t header_guid;
 	size_t     message_len;
 	u8         data[];
@@ -145,7 +150,7 @@ struct smm_variable_communicate_header {
  * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
  *
  */
-struct smm_variable_access {
+struct __packed smm_variable_access {
 	efi_guid_t  guid;
 	efi_uintn_t data_size;
 	efi_uintn_t name_size;
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index b8fb2701a7..d292f57244 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -61,13 +61,23 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	depends on OPTEE || ARM_FFA_TRANSPORT
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index d404343a7d..8a397ea21b 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -2193,6 +2193,13 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 			debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
 #endif
 
+#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE) && !CONFIG_IS_ENABLED(SANDBOX_FFA)
+		if (ffa_copy_runtime_data())
+			printf("ERROR: EFI: FFA: copying runtime data\n");
+		else
+			printf("INFO: EFI: FFA: runtime data copied\n");
+#endif
+
 	/* Patch out unsupported runtime function */
 	efi_runtime_detach();
 
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..d6f24f85bd 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,6 +4,8 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright (C) 2022 ARM Limited
+ *  Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -15,6 +17,36 @@
 #include <malloc.h>
 #include <mm_communication.h>
 
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+#include <arm_ffa.h>
+#include <cpu_func.h>
+#include <mapmem.h>
+
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+#warning "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_SIZE 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_OFFSET
+#warning "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_OFFSET 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+#warning "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_ADDR 0
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+
+const char *mm_sp_svc_uuid = MM_SP_UUID;
+
+static __efi_runtime_data u16 mm_sp_id;
+
+#endif
+
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -24,6 +56,7 @@ struct mm_connection {
 	u32 session;
 };
 
+#if (IS_ENABLED(CONFIG_OPTEE))
 /**
  * get_connection() - Retrieve OP-TEE session for a specific UUID.
  *
@@ -143,16 +176,227 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 
 	return ret;
 }
+#endif
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notifies the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int __efi_runtime ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret = -1;
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
+
+	ret = ffa_bus_ops_get()->sync_send_receive(mm_sp_id, &msg);
+	if (ret != 0)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	if (sp_event_ret == MM_SUCCESS)
+		return 0;
+
+	/*
+	 * Failure to notify the MM SP
+	 */
+
+	return -EACCES;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0, size = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &count, NULL);
+	if (ret != 0) {
+		log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
+		return ret;
+	}
+
+	if (!count) {
+		log_info("EFI: No MM partition found\n");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	size = count * sizeof(struct ffa_partition_info);
+
+	/*
+	 * ask the driver to fill the
+	 * buffer with the SPs info
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &size, parts_info);
+	if (ret != 0) {
+		log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * MM SPs found , use the first one
+	 */
+
+	mm_sp_id = parts_info[0].id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t __efi_runtime ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
+		log_err("EFI: Failure to discover MM partition ID at boot time\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	efi_memcpy_runtime(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+	#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+	#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+	if (ffa_ret)
+		unmap_sysmem(virt_shared_buf);
+
+	switch (ffa_ret) {
+	case 0:
+	{
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			unmap_sysmem(virt_shared_buf);
+			return EFI_OUT_OF_RESOURCES;
+		}
+
+		efi_memcpy_runtime(comm_buf, virt_shared_buf, rx_data_size);
+		unmap_sysmem(virt_shared_buf);
+
+		return EFI_SUCCESS;
+	}
+	case -EINVAL:
+		return EFI_DEVICE_ERROR;
+	case -EPERM:
+		return EFI_INVALID_PARAMETER;
+	case -EACCES:
+		return EFI_ACCESS_DENIED;
+	case -EBUSY:
+		return EFI_OUT_OF_RESOURCES;
+	default:
+		return EFI_ACCESS_DENIED;
+	}
+}
+#endif
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, StandAlonneMM and smm-gateway are supported.
+ *
  * Return:		status code
  */
-static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
+static efi_status_t __efi_runtime mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 {
 	efi_status_t ret;
 	struct efi_mm_communicate_header *mm_hdr;
@@ -162,7 +406,11 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
+	#if (IS_ENABLED(CONFIG_OPTEE))
 	ret = optee_mm_communicate(comm_buf, dsize);
+	#elif (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+	ret = ffa_mm_communicate(comm_buf, dsize);
+	#endif
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -258,6 +506,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
 		goto out;
 	}
 	*size = var_payload->size;
+
+	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
+			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
+				MM_VARIABLE_COMMUNICATE_SIZE;
+	#endif
+
 	/*
 	 * There seems to be a bug in EDK2 miscalculating the boundaries and
 	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
@@ -697,7 +952,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v5 10/10] arm_ffa: corstone1000: enable EFI MM communication
  2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                     ` (8 preceding siblings ...)
  2022-09-26 14:08                                   ` [PATCH v5 09/10] arm_ffa: introduce FF-A MM communication Abdellatif El Khlifi
@ 2022-09-26 14:08                                   ` Abdellatif El Khlifi
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-09-26 14:08 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong

turn on EFI MM communication

On corstone1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

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>
---
 configs/corstone1000_defconfig | 4 ++++
 include/configs/corstone1000.h | 9 +++++++++
 2 files changed, 13 insertions(+)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index ed2e0fe70a..5028c746c5 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -52,3 +52,7 @@ CONFIG_DM_SERIAL=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760=y
 CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
+# CONFIG_OPTEE is not set
+CONFIG_ARM_FFA_TRANSPORT=y
+CONFIG_ARM_FFA_EFI_RUNTIME_MODE=y
diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
index 8e0230c135..997d0bebaf 100644
--- a/include/configs/corstone1000.h
+++ b/include/configs/corstone1000.h
@@ -14,6 +14,15 @@
 
 #include <linux/sizes.h>
 
+#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
+
+/*
+ * shared buffer physical address used for communication between
+ * u-boot and the MM SP
+ */
+#define FFA_SHARED_MM_BUFFER_ADDR	(0x023F8000)
+#define FFA_SHARED_MM_BUFFER_OFFSET	(0)
+
 #define V2M_BASE		0x80000000
 
 #define CONFIG_PL011_CLOCK	50000000
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v5 09/10] arm_ffa: introduce FF-A MM communication
  2022-09-26 14:08                                   ` [PATCH v5 09/10] arm_ffa: introduce FF-A MM communication Abdellatif El Khlifi
@ 2022-09-29  9:32                                     ` Ilias Apalodimas
  2022-10-14 10:38                                       ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2022-09-29  9:32 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, jens.wiklander, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong, Gowtham Suresh Kumar

Hi Abdellatif, 

> --- a/arch/arm/cpu/armv8/cache.S
> +++ b/arch/arm/cpu/armv8/cache.S
> @@ -3,6 +3,9 @@
>   * (C) Copyright 2013
>   * David Feng <fenghua@phytium.com.cn>
>   *
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + *
>   * This file is based on sample code from ARMv8 ARM.
>   */
>  
> @@ -21,7 +24,11 @@
>   * x1: 0 clean & invalidate, 1 invalidate only
>   * x2~x9: clobbered
>   */
> +#ifdef CONFIG_EFI_LOADER
> +.pushsection .text.efi_runtime, "ax"

Maybe we discussed this in the past and I forgot,  but why would you need 
__asm_dcache_level, __asm_dcache_all, __asm_invalidate_dcache_alla etc in
the runtime section ?

> +#else
>  .pushsection .text.__asm_dcache_level, "ax"
> +#endif
>  ENTRY(__asm_dcache_level)
>  	lsl	x12, x0, #1
>  	msr	csselr_el1, x12		/* select cache level */
> @@ -65,7 +72,11 @@ ENDPROC(__asm_dcache_level)
>   *
>   * flush or invalidate all data cache by SET/WAY.
>   */
> +#ifdef CONFIG_EFI_LOADER
> +.pushsection .text.efi_runtime, "ax"
> +#else
>  .pushsection .text.__asm_dcache_all, "ax"
> +#endif
>  ENTRY(__asm_dcache_all)
>  	mov	x1, x0
>  	dsb	sy
> @@ -109,7 +120,11 @@ ENTRY(__asm_flush_dcache_all)
>  ENDPROC(__asm_flush_dcache_all)
>  .popsection
>  
> +#ifdef CONFIG_EFI_LOADER
> +.pushsection .text.efi_runtime, "ax"
> +#else
>  .pushsection .text.__asm_invalidate_dcache_all, "ax"
> +#endif
>  ENTRY(__asm_invalidate_dcache_all)
>  	mov	x0, #0x1
>  	b	__asm_dcache_all
> @@ -182,7 +197,11 @@ ENTRY(__asm_invalidate_icache_all)
>  ENDPROC(__asm_invalidate_icache_all)
>  .popsection
>  
> +#ifdef CONFIG_EFI_LOADER
> +.pushsection .text.efi_runtime, "ax"
> +#else
>  .pushsection .text.__asm_invalidate_l3_dcache, "ax"
> +#endif
>  WEAK(__asm_invalidate_l3_dcache)
>  	mov	x0, #0			/* return status as success */
>  	ret
> diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
> index e4736e5643..45f57372c2 100644
> --- a/arch/arm/cpu/armv8/cache_v8.c
> +++ b/arch/arm/cpu/armv8/cache_v8.c
> @@ -5,10 +5,14 @@
>   *
>   * (C) Copyright 2016
>   * Alexander Graf <agraf@suse.de>
> + *
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #include <common.h>
>  #include <cpu_func.h>
> +#include <efi_loader.h>
>  #include <hang.h>
>  #include <log.h>
>  #include <asm/cache.h>
> @@ -445,7 +449,7 @@ __weak void mmu_setup(void)
>  /*
>   * Performs a invalidation of the entire data cache at all levels
>   */
> -void invalidate_dcache_all(void)
> +void __efi_runtime invalidate_dcache_all(void)
>  {
>  	__asm_invalidate_dcache_all();
>  	__asm_invalidate_l3_dcache();
> diff --git a/include/mm_communication.h b/include/mm_communication.h
> index e65fbde60d..fe9104c56d 100644
> --- a/include/mm_communication.h

[...]

>   * always begin with efi_mm_communicate_header.
>   */
> -struct __packed efi_mm_communicate_header {
> +struct efi_mm_communicate_header {
>  	efi_guid_t header_guid;
>  	size_t     message_len;
>  	u8         data[];
> @@ -145,7 +150,7 @@ struct smm_variable_communicate_header {
>   * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
>   *
>   */
> -struct smm_variable_access {
> +struct __packed smm_variable_access {

You are randomly adding and deleting __packed cwin both structs. But you can't do that.
Those structs are defined in StandAloneMM.  This is the reason each struct
description has the corresponding EDK2 definition. 

>  	efi_guid_t  guid;
>  	efi_uintn_t data_size;
>  	efi_uintn_t name_size;
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index b8fb2701a7..d292f57244 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -61,13 +61,23 @@ config EFI_VARIABLE_FILE_STORE
>  	  stored as file /ubootefi.var on the EFI system partition.
>  
>  config EFI_MM_COMM_TEE
> -	bool "UEFI variables storage service via OP-TEE"
> -	depends on OPTEE
> +	bool "UEFI variables storage service via the trusted world"
> +	depends on OPTEE || ARM_FFA_TRANSPORT

I think we discussed this in the past.  I don't want ifdefs in the code for
that.  FF-A is a discoverable bus.  So I think what we should do here, is
fire up the variable access driver -> probe for FF-A -> decide what to use.

So it looks something like
    **************************
    **** Variable Driver *****
    **************************
                |
                |
                |
   ***************************
   ****** Discover FF-A ******
   ***************************
        |                 |
	| yes             | No
        |                 |
      
      Use SP          Use OP-TEE

>  	help
> +	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
> +	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> +	  When using the u-boot FF-A  driver any MM SP is supported.
> +
>  	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
>  	  variable related operations to that. The application will verify,
>  	  authenticate and store the variables on an RPMB.
>  
> +	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> +	  operations to the MM SP running in the secure world.
> +	  A door bell mechanism is used to notify the SP when there is data in the shared
> +	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
> +	  the door bell event.
> +
>  config EFI_VARIABLE_NO_STORE
>  	bool "Don't persist non-volatile UEFI variables"
>  	help
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index d404343a7d..8a397ea21b 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -2193,6 +2193,13 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
>  			debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
>  #endif
>  
> +#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE) && !CONFIG_IS_ENABLED(SANDBOX_FFA)
> +		if (ffa_copy_runtime_data())
> +			printf("ERROR: EFI: FFA: copying runtime data\n");
> +		else
> +			printf("INFO: EFI: FFA: runtime data copied\n");
> +#endif
> +
>  	/* Patch out unsupported runtime function */
>  	efi_runtime_detach();
>  
> diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> index dfef18435d..d6f24f85bd 100644
> --- a/lib/efi_loader/efi_variable_tee.c
> +++ b/lib/efi_loader/efi_variable_tee.c
> @@ -4,6 +4,8 @@
>   *
>   *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
>   *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
> + *  Copyright (C) 2022 ARM Limited
> + *  Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #include <common.h>
> @@ -15,6 +17,36 @@
>  #include <malloc.h>
>  #include <mm_communication.h>
>  
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +
> +#include <arm_ffa.h>
> +#include <cpu_func.h>
> +#include <mapmem.h>
> +
> +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> +#warning "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_SIZE 0
> +#endif
> +
> +#ifndef FFA_SHARED_MM_BUFFER_OFFSET
> +#warning "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_OFFSET 0
> +#endif
> +
> +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> +#warning "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_ADDR 0
> +#endif
> +
> +/* MM return codes */
> +#define MM_SUCCESS (0)
> +
> +const char *mm_sp_svc_uuid = MM_SP_UUID;
> +
> +static __efi_runtime_data u16 mm_sp_id;
> +
> +#endif
> +
>  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
>  static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
>  static efi_uintn_t max_payload_size;	/* func + data */
> @@ -24,6 +56,7 @@ struct mm_connection {
>  	u32 session;
>  };
>  
> +#if (IS_ENABLED(CONFIG_OPTEE))
>  /**
>   * get_connection() - Retrieve OP-TEE session for a specific UUID.
>   *
> @@ -143,16 +176,227 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
>  
>  	return ret;
>  }
> +#endif
> +
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
>  
>  /**
> - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
> + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> + *
> + * Notifies the MM partition in the trusted world that
> + * data is available in the shared buffer.
> + * This is a blocking call during which trusted world has exclusive access
> + * to the MM shared buffer.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int __efi_runtime ffa_notify_mm_sp(void)
> +{
> +	struct ffa_send_direct_data msg = {0};
> +	int ret;
> +	int sp_event_ret = -1;
> +
> +	if (!ffa_bus_ops_get())
> +		return -EINVAL;
> +
> +	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
> +
> +	ret = ffa_bus_ops_get()->sync_send_receive(mm_sp_id, &msg);
> +	if (ret != 0)
> +		return ret;
> +
> +	sp_event_ret = msg.data0; /* x3 */
> +
> +	if (sp_event_ret == MM_SUCCESS)
> +		return 0;
> +
> +	/*
> +	 * Failure to notify the MM SP
> +	 */
> +
> +	return -EACCES;
> +}
> +
> +/**
> + * ffa_discover_mm_sp_id() - Query the MM partition ID
> + *
> + * Use the FF-A driver to get the MM partition ID.
> + * If multiple partitions are found, use the first one.
> + * This is a boot time function.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_discover_mm_sp_id(void)
> +{
> +	u32 count = 0, size = 0;
> +	int ret;
> +	struct ffa_partition_info *parts_info;
> +
> +	if (!ffa_bus_ops_get())
> +		return -EINVAL;
> +
> +	/*
> +	 * get from the driver the count of the SPs matching the UUID
> +	 */
> +	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &count, NULL);
> +	if (ret != 0) {
> +		log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
> +		return ret;
> +	}
> +
> +	if (!count) {
> +		log_info("EFI: No MM partition found\n");
> +		return ret;
> +	}
> +
> +	/*
> +	 * pre-allocate a buffer to be filled by the driver
> +	 * with	 ffa_partition_info structs
> +	 */
> +
> +	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
> +
> +	parts_info = calloc(count, sizeof(struct ffa_partition_info));
> +	if (!parts_info)
> +		return -EINVAL;
> +
> +	size = count * sizeof(struct ffa_partition_info);
> +
> +	/*
> +	 * ask the driver to fill the
> +	 * buffer with the SPs info
> +	 */
> +	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &size, parts_info);
> +	if (ret != 0) {
> +		log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret);
> +		free(parts_info);
> +		return ret;
> +	}
> +
> +	/*
> +	 * MM SPs found , use the first one
> +	 */
> +
> +	mm_sp_id = parts_info[0].id;
> +
> +	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
> +
> +	free(parts_info);
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
> + * @comm_buf:		locally allocated communication buffer used for rx/tx
> + * @dsize:				communication buffer size
> + *
> + * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
> + * that there is data to read from the shared buffer.
> + * Communication with the MM SP is performed using FF-A transport.
> + * On the event, MM SP can read the data from the buffer and
> + * update the MM shared buffer with response data.
> + * The response data is copied back to the communication buffer.
> + *
> + * Return:
> + *
> + * EFI status code
> + */
> +static efi_status_t __efi_runtime ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
> +{

If you are registering this as a *runtime* service you should also tweak
the RT_PROPERTIES TABLE and enable runtime services (e.g SetVariable).
Otherwise having as runtime makes little sense.  To be honest I'd much
prefer this whole patchset without the runtime parts.  It's much easier to
review and reason about and we can always add runtime later.

> +	ulong tx_data_size;
> +	int ffa_ret;
> +	struct efi_mm_communicate_header *mm_hdr;
> +	void *virt_shared_buf;
> +
> +	if (!comm_buf)
> +		return EFI_INVALID_PARAMETER;
> +
> +	/* Discover MM partition ID at boot time */
> +	if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
> +		log_err("EFI: Failure to discover MM partition ID at boot time\n");
> +		return EFI_UNSUPPORTED;
> +	}
> +
> +	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> +	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
> +
> +	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
> +		return EFI_INVALID_PARAMETER;
> +
> +	/* Copy the data to the shared buffer */
> +
> +	virt_shared_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
> +	efi_memcpy_runtime(virt_shared_buf, comm_buf, tx_data_size);
> +
> +	/*
> +	 * The secure world might have cache disabled for
> +	 * the device region used for shared buffer (which is the case for Optee).
> +	 * In this case, the secure world reads the data from DRAM.
> +	 * Let's flush the cache so the DRAM is updated with the latest data.
> +	 */
> +	#ifdef CONFIG_ARM64
> +	invalidate_dcache_all();
> +	#endif
> +
> +	/* Announce there is data in the shared buffer */
> +
> +	ffa_ret = ffa_notify_mm_sp();
> +	if (ffa_ret)
> +		unmap_sysmem(virt_shared_buf);
> +
> +	switch (ffa_ret) {
> +	case 0:
> +	{
> +		ulong rx_data_size;
> +		/* Copy the MM SP response from the shared buffer to the communication buffer */
> +		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> +			sizeof(efi_guid_t) +
> +			sizeof(size_t);
> +
> +		if (rx_data_size > comm_buf_size) {
> +			unmap_sysmem(virt_shared_buf);
> +			return EFI_OUT_OF_RESOURCES;
> +		}
> +
> +		efi_memcpy_runtime(comm_buf, virt_shared_buf, rx_data_size);
> +		unmap_sysmem(virt_shared_buf);
> +
> +		return EFI_SUCCESS;
> +	}
> +	case -EINVAL:
> +		return EFI_DEVICE_ERROR;
> +	case -EPERM:
> +		return EFI_INVALID_PARAMETER;
> +	case -EACCES:
> +		return EFI_ACCESS_DENIED;
> +	case -EBUSY:
> +		return EFI_OUT_OF_RESOURCES;
> +	default:
> +		return EFI_ACCESS_DENIED;
> +	}
> +}
> +#endif
> +
> +/**
> + * mm_communicate() - Adjust the communication buffer to the MM SP and send
>   * it to OP-TEE
>   *
> - * @comm_buf:		locally allocted communcation buffer
> + * @comm_buf:		locally allocated communication buffer
>   * @dsize:		buffer size
> + *
> + * The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
> + * The comm_buf format is the same for both partitions.
> + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> + * When using the u-boot FF-A  driver, StandAlonneMM and smm-gateway are supported.
> + *
>   * Return:		status code
>   */
> -static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> +static efi_status_t __efi_runtime mm_communicate(u8 *comm_buf, efi_uintn_t dsize)

The optee version of the function can't be on the efi_runtime section.  The
reason is that almost the entire of the OP-TEE subsystem is not marked as
runtime, which will lead to a crash if we ever take that path.

>  {
>  	efi_status_t ret;
>  	struct efi_mm_communicate_header *mm_hdr;
> @@ -162,7 +406,11 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
>  	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
>  
> +	#if (IS_ENABLED(CONFIG_OPTEE))
>  	ret = optee_mm_communicate(comm_buf, dsize);
> +	#elif (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +	ret = ffa_mm_communicate(comm_buf, dsize);

If we enable runtime discovery of optee vs ffa, we can get rid of that and
just pass an extra argument to mm_communicate

Thanks
/Ilias
> +	#endif
>  	if (ret != EFI_SUCCESS) {
>  		log_err("%s failed!\n", __func__);
>  		return ret;
> @@ -258,6 +506,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
>  		goto out;
>  	}
>  	*size = var_payload->size;
> +
> +	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
> +			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
> +				MM_VARIABLE_COMMUNICATE_SIZE;
> +	#endif
> +
>  	/*
>  	 * There seems to be a bug in EDK2 miscalculating the boundaries and
>  	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> @@ -697,7 +952,7 @@ void efi_variables_boot_exit_notify(void)
>  		ret = EFI_NOT_FOUND;
>  
>  	if (ret != EFI_SUCCESS)
> -		log_err("Unable to notify StMM for ExitBootServices\n");
> +		log_err("Unable to notify the MM partition for ExitBootServices\n");
>  	free(comm_buf);
>  
>  	/*
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v5 02/10] arm64: smccc: clear the Xn registers after SMC calls
  2022-09-26 14:08                                   ` [PATCH v5 02/10] arm64: smccc: clear the Xn registers after SMC calls Abdellatif El Khlifi
@ 2022-09-30  9:48                                     ` Jens Wiklander
  2022-10-14 10:17                                       ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Jens Wiklander @ 2022-09-30  9:48 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, ilias.apalodimas, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong

On Mon, Sep 26, 2022 at 03:08:19PM +0100, Abdellatif El Khlifi wrote:
> set to zero the x0-x17 registers
> 
> As per the SMCCC v1.2 spec, unused result and scratch registers
> can leak information after an SMC call. We can mitigate against
> this risk by returning zero in each register.
> 
> The leakage we are referring to is data leakage across exception
> levels. The intent is to prevent lower exception levels (EL1/EL0)
> from reading the SMC data exchanged at EL2.
> 
> 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>
> ---
> 
> Changelog:
> ===============
> 
> v4:
> 
> * move the clearing code into a new macro: clear_gp_regs
> 
> v3:
> 
> * clear the Xn registers after SMC calls
> 
> 
>  arch/arm/cpu/armv8/smccc-call.S | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
> index ec6f299bc9..32f3eb8eeb 100644
> --- a/arch/arm/cpu/armv8/smccc-call.S
> +++ b/arch/arm/cpu/armv8/smccc-call.S
> @@ -50,6 +50,12 @@ ENDPROC(__arm_smccc_hvc)
>  
>  #ifdef CONFIG_ARM64
>  
> +	.macro	clear_gp_regs
> +	.irp	n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17
> +	mov	x\n, xzr
> +	.endr
> +	.endm
> +
>  	.macro SMCCC_1_2 instr
>  	/* Save `res` and free a GPR that won't be clobbered */
>  	stp     x1, x19, [sp, #-16]!
> @@ -84,6 +90,9 @@ ENDPROC(__arm_smccc_hvc)
>  	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
>  	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
>  
> +	/* x0-x17 registers can leak information after an SMC or HVC call. Let's clear them */
> +	clear_gp_regs
> +

This should in my opinion not be needed. The higher exception level should
only return what it indends to return and certainly not rely on lower
exception levels to try to hide eventual unintentionally revealed
secrets.

In an earlier conversation you said:
> The leakage we are referring to is data leakage across exception levels.
> The intent is to prevent lower exception levels (EL1/EL0) to read the
> data exchanged at EL2.
> 
> The linux kernel clears the general purpose registers before switching
> to EL0. As far as I know u-boot doesn't.
> 
> So, the code above makes sure the registers are cleared.

U-Boot is as far as I know not changing to EL0. Do you have a real example
where this cleaning actually would be needed? If it's needed I'd expect
the cleaning to be done just before changing exception level.

Cheers,
Jens


>  	/* Restore original x19 */
>  	ldp     xzr, x19, [sp], #16
>  	ret
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v5 04/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-09-26 14:08                                   ` [PATCH v5 04/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
@ 2022-10-03  8:49                                     ` Jens Wiklander
  2022-10-03 15:22                                       ` Tom Rini
  2022-10-14 10:28                                       ` Abdellatif El Khlifi
  0 siblings, 2 replies; 478+ messages in thread
From: Jens Wiklander @ 2022-10-03  8:49 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, ilias.apalodimas, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong

On Mon, Sep 26, 2022 at 03:08:21PM +0100, Abdellatif El Khlifi wrote:
> Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
> 
> The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World leveraging TrustZone
> technology.
> 
> This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> querying the FF-A framework from the secure world.
> 
> 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> 
> In u-boot FF-A design, FF-A is considered as a discoverable bus.
> The Secure World is considered as one entity to communicate with
> using the FF-A bus. FF-A communication is handled by one device and
> one instance (the bus). This FF-A driver takes care of all the
> interactions between Normal world and Secure World.
> 
> The driver exports its operations to be used by upper layers.
> 
> Exported operations:
> 
> - partition_info_get
> - sync_send_receive
> - rxtx_unmap
> 
> This implementation provides an optional feature to copy the driver data
> to EFI runtime area.
> 
> [1]: https://developer.arm.com/documentation/den0077/latest/
> 
> 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>
> ---
> 
> Changelog:
> ===============
> 
> v4:
> 
> * add doc/README.ffa.drv
> * moving the FF-A driver work to drivers/firmware/arm-ffa
> * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
>   #if defined by #if CONFIG_IS_ENABLED
> * improving error handling by mapping the FF-A errors to standard errors
>   and logs
> * replacing panics with an error log and returning an error code
> * improving features discovery in FFA_FEATURES by introducing
>   rxtx_min_pages private data field
> * add ffa_remove and ffa_bind functions
> * improve how the driver behaves when bus discovery is done more than
>   once
> 
> v3:
> 
> * align the interfaces of the u-boot FF-A driver with those in the linux
>   FF-A driver
> * remove the FF-A helper layer
> * make the u-boot FF-A driver independent from EFI
> * provide an optional config that enables copying the driver data to EFI
>   runtime section at ExitBootServices service
> * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
> 
> v2:
> 
> * make FF-A bus discoverable using device_{bind, probe} APIs
> * remove device tree support
> 
> v1:
> 
> * introduce FF-A bus driver with device tree support
> 
>  MAINTAINERS                                   |    7 +
>  common/board_r.c                              |    9 +
>  doc/README.ffa.drv                            |  160 ++
>  drivers/Kconfig                               |    2 +
>  drivers/Makefile                              |    1 +
>  drivers/firmware/arm-ffa/Kconfig              |   39 +
>  drivers/firmware/arm-ffa/Makefile             |    7 +
>  drivers/firmware/arm-ffa/arm-ffa-uclass.c     |   16 +
>  drivers/firmware/arm-ffa/arm_ffa_prv.h        |  196 +++
>  drivers/firmware/arm-ffa/core.c               | 1344 +++++++++++++++++
>  .../arm-ffa/efi_ffa_runtime_data_mgr.c        |   94 ++
>  include/arm_ffa.h                             |  127 ++
>  include/dm/uclass-id.h                        |    4 +
>  lib/efi_loader/efi_boottime.c                 |   15 +
>  14 files changed, 2021 insertions(+)
>  create mode 100644 doc/README.ffa.drv
>  create mode 100644 drivers/firmware/arm-ffa/Kconfig
>  create mode 100644 drivers/firmware/arm-ffa/Makefile
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
>  create mode 100644 drivers/firmware/arm-ffa/core.c
>  create mode 100644 drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
>  create mode 100644 include/arm_ffa.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 83346183ee..02b84d5074 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -248,6 +248,13 @@ F:	drivers/net/cortina_ni.h
>  F:	drivers/net/phy/ca_phy.c
>  F:	configs/cortina_presidio-asic-pnand_defconfig
>  
> +ARM FF-A
> +M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +S:	Maintained
> +F:	doc/README.ffa.drv
> +F:	drivers/firmware/arm-ffa/
> +F:	include/arm_ffa.h
> +
>  ARM FREESCALE IMX
>  M:	Stefano Babic <sbabic@denx.de>
>  M:	Fabio Estevam <festevam@gmail.com>
> diff --git a/common/board_r.c b/common/board_r.c
> index 56eb60fa27..8c99faddfd 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -7,6 +7,8 @@
>   * (C) Copyright 2002
>   * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
>   * Marius Groeger <mgroeger@sysgo.de>
> + *
> + * (C) Copyright 2022 ARM Limited
>   */
>  
>  #include <common.h>
> @@ -66,6 +68,10 @@
>  #include <efi_loader.h>
>  #include <relocate.h>
>  
> +#ifdef CONFIG_ARM_FFA_TRANSPORT
> +#include <arm_ffa.h>
> +#endif
> +
>  DECLARE_GLOBAL_DATA_PTR;
>  
>  ulong monitor_flash_len;
> @@ -770,6 +776,9 @@ static init_fnc_t init_sequence_r[] = {
>  	INIT_FUNC_WATCHDOG_RESET
>  	initr_net,
>  #endif
> +#ifdef CONFIG_ARM_FFA_TRANSPORT
> +	ffa_bus_discover,
> +#endif
>  #ifdef CONFIG_POST
>  	initr_post,
>  #endif
> diff --git a/doc/README.ffa.drv b/doc/README.ffa.drv
> new file mode 100644
> index 0000000000..1c0a33deb8
> --- /dev/null
> +++ b/doc/README.ffa.drv
> @@ -0,0 +1,160 @@
> +Arm FF-A Driver
> +====================
> +
> +Introduction
> +--------------------
> +
> +FF-A stands for Firmware Framework for Arm A-profile processors.
> +
> +FF-A specifies interfaces that enable a pair of software sandboxes to communicate with each other. A sandbox aka partition could
> +be a VM in the Normal or Secure world, an application in S-EL0, or a Trusted OS in S-EL1.

These lines are a bit long, from the coding guide lines:
The preferred limit on the length of a single line is 80 columns.

> +
> +This FF-A driver implements the interfaces to communicate with partitions in the Secure world aka Secure partitions (SPs).
> +
> +The driver specifically focuses on communicating with SPs that isolate portions of EFI runtime services that must run in a
> +protected environment which is inaccessible by the Host OS or Hypervisor. Examples of such services are set/get variables.
> +
> +FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> +
> +- Discover the presence of SPs of interest.
> +- Access an SP's service through communication protocols e.g. EFI MM communication protocol.
> +
> +FF-A and SMC specifications
> +-------------------------------------------
> +
> +The current implementation of the driver relies on FF-A specification v1.0 and uses SMC32 calling convention.
> +
> +The driver has been tested with Optee OS which supports SMC32 for most of the SMC ABIs.
> +
> +For more details please refer to: https://developer.arm.com/documentation/den0077/a/?lang=en
> +
> +The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
> +
> +For more details please refer to: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
> +
> +Supported hardware
> +--------------------------------
> +
> +Aarch64 plaforms
> +
> +Configuration
> +----------------------
> +
> +CONFIG_ARM_FFA_TRANSPORT
> +    Enables the FF-A bus driver. Turn this on if you want to use FF-A communication.
> +
> +CONFIG_ARM_FFA_EFI_RUNTIME_MODE
> +    Optional config that enables EFI runtime support for FF-A data and code.
> +    ffa_copy_runtime_data allows to copy the FF-A driver data structures to EFI runtime data section.
> +    Turning the config on makes ffa_copy_runtime_data available for use and the driver code placed at EFI runtime code section.
> +    Call ffa_copy_runtime_data at the event on which you want the FF-A data to be copied (example: at ExitBootServices).
> +
> +CONFIG_SANDBOX_FFA
> +    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under Sandbox and provides
> +    functional tests for FF-A.
> +
> +FF-A ABIs under the hood
> +---------------------------------------
> +
> +Invoking an FF-A ABI involves providing to the secure world/hypervisor the expected arguments from the ABI.
> +
> +The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction is executed.
> +
> +At the secure side level or hypervisor the ABI is handled at a higher exception level and the arguments are read and processed.
> +
> +The response is put back through x0 to x7 registers and control is giving back to the u-boot FF-A driver (non secure world).

U-Boot, non-secure

> +
> +The driver reads the response and processes it accordingly.
> +
> +This methodology applies to all the FF-A ABIs in the driver.
> +
> +FF-A bus discovery in u-boot

U-Boot, you might as well search and replace.

> +-------------------------------------------
> +
> +When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is automatically discovered at initcall level (after u-boot relocation).
> +
> +The function that triggers the discovery process is ffa_bus_discover.
> +
> +ffa_bus_discover creates, binds and probes the arm_ffa device using device_{bind, probe} APIs.
> +
> +When the device is probed, ffa_probe is called which tries to communicate with the secure world or hypervisor.
> +
> +The FF-A bus is usable when these checks succeed:
> +
> +- querying the FF-A framework version
> +- querying from secure world the u-boot endpoint ID
> +- querying from secure world the supported features of the specified FF-A calls
> +- mapping the RX/TX buffers
> +- querying from secure world all the partitions information
> +
> +Probing fails when any of these operations fail. The FF-A bus discovery succeeds when probing is successful.
> +
> +When discovery fails the arm_ffa device is destroyed.
> +
> +The bus driver layer
> +------------------------------
> +
> +The driver comes on top of the SMCCC layer and is implemented in drivers/firmware/arm-ffa/core.c
> +
> +The driver provides the following features:
> +
> +- Support for the 32-bit version of the following ABIs:
> +
> +FFA_VERSION
> +FFA_ID_GET
> +FFA_FEATURES
> +FFA_PARTITION_INFO_GET
> +FFA_RXTX_UNMAP
> +FFA_RX_RELEASE
> +FFA_RUN
> +FFA_ERROR
> +FFA_SUCCESS
> +FFA_INTERRUPT
> +
> +- Support for the 64-bit version of the following ABIs:
> +
> +FFA_RXTX_MAP
> +FFA_MSG_SEND_DIRECT_REQ
> +FFA_MSG_SEND_DIRECT_RESP
> +
> +- Processing the received data from the secure world/hypervisor and caching it
> +
> +- Hiding from upper layers the FF-A protocol and registers details. Upper layers focus on exchanged data,
> +the driver takes care of how to transport that to the secure world/hypervisor using FF-A.
> +
> +- The driver provides callbacks to be used by clients to access the FF-A bus:
> +
> +partition_info_get
> +sync_send_receive
> +rxtx_unmap
> +
> +- FF-A bus discovery at initcalls level (after u-boot relocation). The bus is up and running if the FF-A framework is responsive and compatible with the driver.
> +
> +- When EFI is enabled, unmap the RX/TX buffers at ExitBootServices() level.
> +
> +- When CONFIG_ARM_FFA_EFI_RUNTIME_MODE enabled, ffa_copy_runtime_data function is available for use.
> +
> +Using armffa command
> +-----------------------------------
> +
> +armffa is a command showcasing how to use the FF-A driver and how to invoke its operations.
> +
> +This provides a guidance to the client developers on how to call the FF-A bus interfaces.
> +
> +Usage:
> +
> +armffa <sub-command> <arguments>
> +
> +sub-commands:
> +
> +        getpart <partition UUID>
> +
> +            lists the partition(s) info
> +
> +        ping <partition ID>
> +
> +            sends a data pattern to the specified partition
> +
> +        devlist
> +
> +            displays the arm_ffa device info
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index 8b6fead351..b06b1ae481 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
>  
>  source "drivers/adc/Kconfig"
>  
> +source "drivers/firmware/arm-ffa/Kconfig"
> +
>  source "drivers/ata/Kconfig"
>  
>  source "drivers/axi/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index eba9940231..c3bfad94ac 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -110,6 +110,7 @@ obj-y += iommu/
>  obj-y += smem/
>  obj-y += thermal/
>  obj-$(CONFIG_TEE) += tee/
> +obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
>  obj-y += axi/
>  obj-y += ufs/
>  obj-$(CONFIG_W1) += w1/
> diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> new file mode 100644
> index 0000000000..aceb61cf49
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/Kconfig
> @@ -0,0 +1,39 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +config ARM_FFA_TRANSPORT
> +	bool "Enable Arm Firmware Framework for Armv8-A driver"
> +	depends on DM && ARM64
> +	select ARM_SMCCC
> +	select LIB_UUID
> +	select DEVRES
> +	help
> +	  The Firmware Framework for Arm A-profile processors (FF-A)
> +	  describes interfaces (ABIs) that standardize communication
> +	  between the Secure World and Normal World leveraging TrustZone
> +	  technology.
> +
> +	  This driver is based on FF-A specification v1.0 and uses SMC32
> +	  calling convention.
> +
> +	  FF-A specification:
> +
> +	  https://developer.arm.com/documentation/den0077/a/?lang=en
> +
> +	  In u-boot FF-A design, FF-A is considered as a discoverable bus.
> +	  The Secure World is considered as one entity to communicate with
> +	  using the FF-A bus.
> +	  FF-A communication is handled by one device and one instance (the bus).
> +	  This FF-A driver takes care of all the interactions between Normal world
> +	  and Secure World.
> +
> +	  For more details about the FF-A driver, please refer to doc/README.ffa.drv
> +
> +config ARM_FFA_EFI_RUNTIME_MODE
> +	bool "Enable EFI runtime support for FF-A data and code"
> +	depends on ARM_FFA_TRANSPORT && EFI_LOADER
> +	help
> +	  Allows FF-A driver data structures and code to be accessible at EFI runtime.
> +	  FF-A data is copied by ffa_copy_runtime_data function.
> +	  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.
> diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
> new file mode 100644
> index 0000000000..0b9b0a61b4
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/Makefile
> @@ -0,0 +1,7 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +#
> +
> +obj-y += arm-ffa-uclass.o core.o
> +obj-$(CONFIG_ARM_FFA_EFI_RUNTIME_MODE) += efi_ffa_runtime_data_mgr.o
> diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> new file mode 100644
> index 0000000000..7d9695d289
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> @@ -0,0 +1,16 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <asm/global_data.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +UCLASS_DRIVER(ffa) = {
> +	.name		= "ffa",
> +	.id		= UCLASS_FFA,
> +};
> diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> new file mode 100644
> index 0000000000..7bc90f7f66
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> @@ -0,0 +1,196 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#ifndef __ARM_FFA_PRV_H
> +#define __ARM_FFA_PRV_H
> +
> +#include <arm_ffa.h>
> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
> +#include <linux/arm-smccc.h>
> +
> +/*
> + * This header is private. It is exclusively used by the FF-A driver
> + */
> +
> +/* FF-A core driver name */
> +#define FFA_DRV_NAME "arm_ffa"
> +
> +/* FF-A driver version definitions */
> +
> +#define MAJOR_VERSION_MASK		GENMASK(30, 16)
> +#define MINOR_VERSION_MASK		GENMASK(15, 0)
> +#define GET_FFA_MAJOR_VERSION(x)		\
> +				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> +#define GET_FFA_MINOR_VERSION(x)		\
> +				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> +#define PACK_VERSION_INFO(major, minor)			\
> +	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
> +	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> +
> +#define FFA_MAJOR_VERSION		(1)
> +#define FFA_MINOR_VERSION		(0)
> +#define FFA_VERSION_1_0		\
> +			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> +
> +/* Endpoint ID mask (u-boot endpoint ID) */
> +
> +#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
> +#define GET_SELF_ENDPOINT_ID(x)		\
> +			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> +
> +#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
> +#define PREP_SELF_ENDPOINT_ID(x)		\
> +			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> +
> +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> +
> +#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
> +#define PREP_PART_ENDPOINT_ID(x)		\
> +			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> +
> +/*
> + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> + */
> +
> +#define FFA_SMC(calling_convention, func_num)				\
> +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
> +			   ARM_SMCCC_OWNER_STANDARD, (func_num))
> +
> +#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> +#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
> +
> +enum ffa_abis {
> +	FFA_ERROR					= 0x60,
> +	FFA_SUCCESS					= 0x61,
> +	FFA_INTERRUPT				= 0x62,
> +	FFA_VERSION					= 0x63,
> +	FFA_FEATURES				= 0x64,
> +	FFA_RX_RELEASE				= 0x65,
> +	FFA_RXTX_MAP				= 0x66,
> +	FFA_RXTX_UNMAP			= 0x67,
> +	FFA_PARTITION_INFO_GET		= 0x68,
> +	FFA_ID_GET					= 0x69,
> +	FFA_RUN						= 0x6D,
> +	FFA_MSG_SEND_DIRECT_REQ	= 0x6F,
> +	FFA_MSG_SEND_DIRECT_RESP	= 0x70,
> +
> +	/* to be updated when adding new FFA IDs */
> +	FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
> +	FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
> +};
> +
> +/* number of the errors supported by the FF-A specification */
> +#define MAX_NUMBER_FFA_ERR 9
> +
> +/* container structure and helper macros to map between an FF-A error and relevant error log */
> +struct ffa_abi_errmap {
> +	char *err_str[MAX_NUMBER_FFA_ERR];
> +};
> +
> +#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
> + *
> + */
> +struct ffa_partition_uuid {
> +	u32 a1; /* w1 */
> +	u32 a2; /* w2 */
> +	u32 a3; /* w3 */
> +	u32 a4; /* w4 */
> +};
> +
> +/**
> + * enum ffa_rxtx_buf_sizes - minimum sizes supported
> + * for the RX/TX buffers
> + */
> +enum ffa_rxtx_buf_sizes {
> +	RXTX_4K,
> +	RXTX_64K,
> +	RXTX_16K
> +};
> +
> +/**
> + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> + * @rxbuf:	virtual address of the RX buffer
> + * @txbuf:	virtual address of the TX buffer
> + * @rxtx_min_pages:	RX/TX buffers minimum size in pages
> + *
> + * Data structure hosting the virtual addresses of the mapped RX/TX buffers
> + * These addresses are used by the FF-A functions that use the RX/TX buffers
> + */
> +struct ffa_rxtxpair {
> +	u64 rxbuf; /* virtual address */
> +	u64 txbuf; /* virtual address */
> +	size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
> +};
> +
> +/**
> + * struct ffa_partition_desc - the secure partition descriptor
> + * @info:	partition information
> + * @sp_uuid:	the secure partition UUID
> + *
> + * Each partition has its descriptor containing the partitions information and the UUID
> + */
> +struct ffa_partition_desc {
> +	struct ffa_partition_info info;
> +	struct ffa_partition_uuid sp_uuid;
> +};
> +
> +/**
> + * struct ffa_partitions - descriptors for all secure partitions
> + * @count:	The number of partitions descriptors
> + * @descs	The partitions descriptors table
> + *
> + * This data structure contains the partitions descriptors table
> + */
> +struct ffa_partitions {
> +	u32 count;
> +	struct ffa_partition_desc *descs; /* virtual address */
> +};
> +
> +/**
> + * struct ffa_prvdata - the driver private data structure
> + *
> + * @dev:	The arm_ffa device under u-boot driver model
> + * @ffa_ops:	The driver operations structure
> + * @fwk_version:	FF-A framework version
> + * @id:	u-boot endpoint ID
> + * @partitions:	The partitions descriptors structure
> + * @pair:	The RX/TX buffers pair
> + * @invoke_ffa_fn:	The function executing the FF-A function
> + *
> + * The driver data structure hosting all resident data.
> + */
> +struct ffa_prvdata {
> +	struct udevice *dev;
> +	struct ffa_bus_ops ffa_ops;
> +	u32 fwk_version;
> +	u16 id;
> +	struct ffa_partitions partitions;
> +	struct ffa_rxtxpair pair;
> +	invoke_ffa_fn_t invoke_ffa_fn;
> +};
> +
> +/**
> + * ffa_device_get - create, bind and probe the arm_ffa device
> + */
> +int ffa_device_get(void);
> +
> +/**
> + * ffa_bus_prvdata_get - bus driver private data getter
> + */
> +struct ffa_prvdata **ffa_bus_prvdata_get(void);
> +
> +#endif
> diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
> new file mode 100644
> index 0000000000..41c7b96e68
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/core.c
> @@ -0,0 +1,1344 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include "arm_ffa_prv.h"
> +#include <asm/global_data.h>
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/device-internal.h>
> +#include <dm/devres.h>
> +#include <dm/root.h>
> +#include <linux/errno.h>
> +#include <linux/sizes.h>
> +#include <log.h>
> +#include <malloc.h>
> +#include <string.h>
> +#include <uuid.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/**
> + * The device private data structure containing all the resident
> + * data read from secure world
> + */
> +__ffa_runtime_data struct ffa_prvdata *ffa_priv_data;
> +
> +/* Error mapping declarations */
> +
> +__ffa_runtime_data int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
> +	0,
> +	-EOPNOTSUPP,	/* NOT_SUPPORTED */
> +	-EINVAL,	/* INVALID_PARAMETERS */
> +	-ENOMEM,	/* NO_MEMORY */
> +	-EBUSY,		/* BUSY */
> +	-EINTR,		/* INTERRUPTED */
> +	-EACCES,	/* DENIED */
> +	-EAGAIN,	/* RETRY */
> +	-ECANCELED,	/* ABORTED */
> +};
> +
> +struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
> +	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
> +		{
> +			"",
> +			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
> +			"", /* INVALID_PARAMETERS */
> +			"", /* NO_MEMORY */
> +			"", /* BUSY */
> +			"", /* INTERRUPTED */
> +			"", /* DENIED */
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
> +		{
> +			"",
> +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> +			"", /* INVALID_PARAMETERS */
> +			"", /* NO_MEMORY */
> +			"", /* BUSY */
> +			"", /* INTERRUPTED */
> +			"", /* DENIED */
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
> +		{
> +			"",
> +			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
> +			"", /* INVALID_PARAMETERS */
> +			"", /* NO_MEMORY */
> +			"", /* BUSY */
> +			"", /* INTERRUPTED */
> +			"", /* DENIED */
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
> +		{
> +			"",
> +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> +			"INVALID_PARAMETERS: Unrecognized UUID",
> +			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
> +			"BUSY: RX buffer of the caller is not free",
> +			"", /* INTERRUPTED */
> +			"DENIED: Callee is not in a state to handle this request",
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
> +			{
> +			"",
> +			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
> +			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
> +			"", /* NO_MEMORY */
> +			"", /* BUSY */
> +			"", /* INTERRUPTED */
> +			"", /* DENIED */
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
> +			{
> +			"",
> +			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
> +			"", /* INVALID_PARAMETERS */
> +			"", /* NO_MEMORY */
> +			"", /* BUSY */
> +			"", /* INTERRUPTED */
> +			"DENIED: Caller did not have ownership of the RX buffer",
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
> +			{
> +			"",
> +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> +			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
> +			"NO_MEMORY: Not enough memory",
> +			"", /* BUSY */
> +			"", /* INTERRUPTED */
> +			"DENIED: Buffer pair already registered",
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +};
> +
> +/**
> + * ffa_to_std_errno - convert FF-A error code to standard error code
> + * @ffa_errno:	Error code returned by the FF-A ABI
> + *
> + * This runtime function maps the given FF-A error code as specified
> + * by the spec to a u-boot standard error code.
> + *
> + * Return:
> + *
> + * The standard error code on success. . Otherwise, failure
> + */
> +__ffa_runtime int ffa_to_std_errno(int ffa_errno)
> +{
> +	int err_idx = -ffa_errno;
> +
> +	/* map the FF-A error code to the standard u-boot error code */
> +	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
> +		return ffa_to_std_errmap[err_idx];
> +	return -EINVAL;
> +}
> +
> +/**
> + * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
> + * @ffa_id:	FF-A ABI ID
> + * @ffa_errno:	Error code returned by the FF-A ABI
> + *
> + * This boot time function maps the FF-A error code to the error log relevant to the
> + * selected FF-A ABI. Then the error log is printed.
> + *
> + * Return:
> + *
> + * 0 on success. . Otherwise, failure
> + */
> +int ffa_print_error_log(u32 ffa_id, int ffa_errno)
> +{
> +	int err_idx = -ffa_errno, abi_idx = 0;
> +
> +	/* map the FF-A error code to the corresponding error log */
> +
> +	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
> +		return -EINVAL;
> +
> +	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
> +		return -EINVAL;
> +
> +	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
> +	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
> +		return -EINVAL;
> +
> +	if (!err_msg_map[abi_idx].err_str || !err_msg_map[abi_idx].err_str[err_idx])
> +		return -EINVAL;
> +
> +	ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
> +
> +	return 0;
> +}
> +
> +/*
> + * Driver core functions
> + */
> +
> +/**
> + * ffa_remove_device - removes the arm_ffa device
> + * @dev:	the device to be removed
> + *
> + * This boot time function makes sure the arm_ffa device is removed
> + * No need to free the kmalloced data when the device is destroyed.
> + * It's automatically done by devm management by
> + * device_remove() -> device_free() -> devres_release_probe().
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_remove_device(struct udevice *dev)
> +{
> +	int ret;
> +
> +	if (!dev) {
> +		ffa_err("no udevice found");
> +		return -ENODEV;
> +	}
> +
> +	ret = device_remove(dev, DM_REMOVE_NORMAL);
> +	if (ret) {
> +		ffa_err("unable to remove. err:%d\n", ret);
> +		return ret;
> +	}
> +
> +	ffa_info("device removed and freed");
> +
> +	ret = device_unbind(dev);
> +	if (ret) {
> +		ffa_err("unable to unbind. err:%d\n", ret);
> +		return ret;
> +	}
> +
> +	ffa_info("device unbound");
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_device_get - create, bind and probe the arm_ffa device
> + *
> + * This boot time function makes sure the arm_ffa device is
> + * created, bound to this driver, probed and ready to use.
> + * Arm FF-A transport is implemented through a single u-boot
> + * device managing the FF-A bus (arm_ffa).
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_device_get(void)
> +{
> +	int ret;
> +	struct udevice *dev = NULL;
> +
> +	ret = device_bind(dm_root(),
> +			  DM_DRIVER_GET(arm_ffa),
> +			  FFA_DRV_NAME,
> +			  NULL,
> +			  ofnode_null(),
> +			  &dev);
> +	if (ret)
> +		return ret;
> +
> +	/* The FF-A bus discovery succeeds when probing is successful */
> +	ret = device_probe(dev);
> +	if (ret) {
> +		ffa_err("arm_ffa device probing failed");
> +		ffa_remove_device(dev);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_get_version - FFA_VERSION handler function
> + *
> + * This is the boot time function that implements FFA_VERSION FF-A function
> + * to get from the secure world the FF-A framework version
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_get_version(void)
> +{
> +	u16 major, minor;
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_VERSION),
> +			.a1 = FFA_VERSION_1_0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,

Why not support the latest version, 1.1?

The zero initializations are done implicitly so you could just as well remove
them.

> +			}, &res);
> +
> +	ffa_errno = (int)res.a0;

Is this cast needed, or any of the other casts below in this function?

> +	if (ffa_errno < 0) {
> +		ffa_print_error_log(FFA_VERSION, ffa_errno);
> +		return ffa_to_std_errno(ffa_errno);
> +	}
> +
> +	major = GET_FFA_MAJOR_VERSION((u32)res.a0);
> +	minor = GET_FFA_MINOR_VERSION((u32)res.a0);
> +
> +	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> +		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> +
> +	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
> +		ffa_info("Versions are compatible ");
> +
> +		ffa_priv_data->fwk_version = (u32)res.a0;
> +
> +		return 0;
> +	}
> +
> +	ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
> +		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> +
> +	return -EPROTONOSUPPORT;
> +}
> +
> +/**
> + * ffa_get_endpoint_id - FFA_ID_GET handler function
> + *
> + * This is the boot time function that implements FFA_ID_GET FF-A function
> + * to get from the secure world u-boot endpoint ID
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_get_endpoint_id(void)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_ID_GET),
> +			.a1 = 0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
> +		ffa_info("endpoint ID is %u", ffa_priv_data->id);
> +
> +		return 0;
> +	}
> +
> +	ffa_errno = (int)res.a2;
> +
> +	ffa_print_error_log(FFA_ID_GET, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
> + * @prop_field: properties field obtained from FFA_FEATURES ABI
> + *
> + * This boot time function sets the minimum number of pages
> + *  in each of the RX/TX buffers in the private data structure
> + *
> + * Return:
> + *
> + * buf_4k_pages points to the returned number of pages
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
> +{
> +	if (!ffa_priv_data)
> +		return -EINVAL;
> +
> +	switch (prop_field) {
> +	case RXTX_4K:
> +		ffa_priv_data->pair.rxtx_min_pages = 1;
> +		break;
> +	case RXTX_16K:
> +		ffa_priv_data->pair.rxtx_min_pages = 4;
> +		break;
> +	case RXTX_64K:
> +		ffa_priv_data->pair.rxtx_min_pages = 16;
> +		break;
> +	default:
> +		ffa_err("RX/TX buffer size not supported");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
> + *
> + * This is the boot time function that implements FFA_FEATURES FF-A function
> + * to retrieve the FFA_RXTX_MAP features
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_get_rxtx_map_features(void)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_FEATURES),
> +			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
> +			.a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> +		return ffa_set_rxtx_buffers_pages_cnt((u32)res.a2);
> +
> +	ffa_errno = (int)res.a2;
> +	ffa_print_error_log(FFA_FEATURES, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> + *
> + * This is the boot time function used to free the RX/TX buffers
> + *
> + */
> +static void ffa_free_rxtx_buffers(void)
> +{
> +	ffa_info("Freeing RX/TX buffers");
> +
> +	if (ffa_priv_data->pair.rxbuf) {
> +		free((void *)ffa_priv_data->pair.rxbuf);
> +		ffa_priv_data->pair.rxbuf = 0;
> +	}
> +
> +	if (ffa_priv_data->pair.txbuf) {
> +		free((void *)ffa_priv_data->pair.txbuf);
> +		ffa_priv_data->pair.txbuf = 0;
> +	}
> +}
> +
> +/**
> + * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
> + *
> + * This is the boot time function used by ffa_map_rxtx_buffers to allocate
> + * the RX/TX buffers before mapping them. The allocated memory is physically
> + * contiguous since memalign ends up calling malloc which allocates
> + * contiguous memory in u-boot.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_alloc_rxtx_buffers(void)
> +{
> +	u64 bytes;
> +
> +	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
> +		 ffa_priv_data->pair.rxtx_min_pages);
> +
> +	bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> +
> +	/* RX/TX buffers addresses should be PAGE_SIZE aligned */
> +
> +	ffa_priv_data->pair.rxbuf = (u64)memalign(PAGE_SIZE, bytes);

Shouldn't this be "bytes" aligned too? Same below with the TX buffer.

> +	if (!ffa_priv_data->pair.rxbuf) {
> +		ffa_err("failure to allocate RX buffer");
> +		return -ENOBUFS;
> +	}
> +
> +	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
> +
> +	ffa_priv_data->pair.txbuf = (u64)memalign(PAGE_SIZE, bytes);
> +	if (!ffa_priv_data->pair.txbuf) {
> +		free((void *)ffa_priv_data->pair.rxbuf);
> +		ffa_priv_data->pair.rxbuf = 0;
> +		ffa_err("failure to allocate the TX buffer");
> +		return -ENOBUFS;
> +	}
> +
> +	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
> +
> +	/*
> +	 * make sure the buffers are cleared before use
> +	 */
> +	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
> +	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> + *
> + * This is the boot time function that implements FFA_RXTX_MAP FF-A function
> + * to map the RX/TX buffers
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_map_rxtx_buffers(void)
> +{
> +	int ret;
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ret = ffa_alloc_rxtx_buffers();
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * we need to pass the physical addresses of the RX/TX buffers
> +	 * in u-boot physical/virtual mapping is 1:1
> +	 *no need to convert from virtual to physical
> +	 */
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
> +			.a1 = ffa_priv_data->pair.txbuf,
> +			.a2 = ffa_priv_data->pair.rxbuf,
> +			.a3 = ffa_priv_data->pair.rxtx_min_pages,
> +			.a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		ffa_info("RX/TX buffers mapped");
> +		return 0;
> +	}
> +
> +	ffa_errno = (int)res.a2;
> +	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
> +
> +	ffa_free_rxtx_buffers();
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
> + *
> + * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function
> + * to unmap the RX/TX buffers
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_unmap_rxtx_buffers(void)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
> +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id),
> +			.a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		ffa_free_rxtx_buffers();
> +		return 0;
> +	}
> +
> +	ffa_errno = (int)res.a2;
> +	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
> + *
> + * This is the boot time function that invokes FFA_RX_RELEASE FF-A function
> + * to release the ownership of the RX buffer
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_release_rx_buffer(void)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
> +			.a1 = 0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> +		return 0;
> +
> +	ffa_errno = (int)res.a2;
> +	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_uuid_are_identical - checks whether two given UUIDs are identical
> + * @uuid1: first UUID
> + * @uuid2: second UUID
> + *
> + * This is a boot time function used by ffa_read_partitions_info to search
> + * for a UUID in the partitions descriptors table
> + *
> + * Return:
> + *
> + * 1 when UUIDs match. Otherwise, 0
> + */
> +int ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
> +			   const struct ffa_partition_uuid *uuid2)
> +{
> +	if (!uuid1 || !uuid2)
> +		return 0;
> +
> +	return (!memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid)));

Please drop the outer ().

> +}
> +
> +/**
> + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> + *							and saves it in the private structure
> + * @count: The number of partitions queried
> + * @part_uuid: Pointer to the partition(s) UUID
> + *
> + * This is the boot time function that reads the partitions information
> + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> + * data structure.
> + *
> + * Return:
> + *
> + * The private data structure is updated with the partition(s) information
> + * 0 is returned on success. Otherwise, failure
> + */
> +static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
> +{
> +	if (!count) {
> +		ffa_err("no partition detected");
> +		return -ENODATA;
> +	}
> +
> +	ffa_info("Reading partitions data from the RX buffer");
> +
> +	if (!part_uuid) {
> +		/*
> +		 * querying information of all partitions
> +		 */
> +		u64 buf_bytes;
> +		u64 data_bytes;
> +		u32 desc_idx;
> +		struct ffa_partition_info *parts_info;
> +
> +		data_bytes = count * sizeof(struct ffa_partition_desc);
> +
> +		buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> +
> +		if (data_bytes > buf_bytes) {
> +			ffa_err("partitions data size exceeds the RX buffer size:");
> +			ffa_err("    sizes in bytes: data %llu , RX buffer %llu ",
> +				data_bytes,
> +				buf_bytes);
> +
> +			return -ENOMEM;
> +		}
> +
> +		ffa_priv_data->partitions.descs = (struct ffa_partition_desc *)
> +			devm_kmalloc(ffa_priv_data->dev, data_bytes, __GFP_ZERO);

There's no need to cast the void pointer.

> +		if (!ffa_priv_data->partitions.descs) {
> +			ffa_err("cannot  allocate partitions data buffer");
> +			return -ENOMEM;
> +		}
> +
> +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> +
> +		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
> +			ffa_priv_data->partitions.descs[desc_idx].info =
> +				parts_info[desc_idx];
> +
> +			ffa_info("Partition ID %x : info cached",
> +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> +		}
> +
> +		ffa_priv_data->partitions.count = count;
> +
> +		ffa_info("%d partition(s) found and cached", count);
> +
> +	} else {
> +		u32 rx_desc_idx, cached_desc_idx;
> +		struct ffa_partition_info *parts_info;
> +		u8 desc_found;
> +
> +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> +
> +		/*
> +		 * search for the SP IDs read from the RX buffer
> +		 * in the already cached SPs.
> +		 * Update the UUID when ID found.
> +		 */
> +		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
> +			desc_found = 0;
> +
> +			/*
> +			 * search the current ID in the cached partitions
> +			 */
> +			for (cached_desc_idx = 0;
> +			     cached_desc_idx < ffa_priv_data->partitions.count;
> +			     cached_desc_idx++) {
> +				/*
> +				 * save the UUID
> +				 */
> +				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
> +				    parts_info[rx_desc_idx].id) {
> +					ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
> +						*part_uuid;
> +
> +					desc_found = 1;
> +					break;
> +				}
> +			}
> +
> +			if (!desc_found)
> +				return -ENODATA;
> +		}
> +	}
> +
> +	return  0;
> +}
> +
> +/**
> + * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
> + *
> + * @part_uuid: Pointer to the partition(s) UUID
> + * @pcount: Pointer to the number of partitions variable filled when querying
> + *
> + * This is the boot time function that executes the FFA_PARTITION_INFO_GET
> + * to query the partitions data. Then, it calls ffa_read_partitions_info
> + * to save the data in the private data structure.
> + *
> + * After reading the data the RX buffer is released using ffa_release_rx_buffer
> + *
> + * Return:
> + *
> + * When part_uuid is NULL, all partitions data are retrieved from secure world
> + * When part_uuid is non NULL, data for partitions matching the given UUID are
> + * retrieved and the number of partitions is returned
> + * 0 is returned on success. Otherwise, failure
> + */
> +static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
> +				     u32 *pcount)
> +{
> +	struct ffa_partition_uuid query_uuid = {0};
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	/*
> +	 * If a UUID is specified. Information for one or more
> +	 * partitions in the system is queried. Otherwise, information
> +	 * for all installed partitions is queried
> +	 */
> +
> +	if (part_uuid) {
> +		if (!pcount)
> +			return -EINVAL;
> +
> +		query_uuid = *part_uuid;
> +	} else if (pcount) {
> +		return -EINVAL;
> +	}
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
> +			.a1 = query_uuid.a1,
> +			.a2 = query_uuid.a2,
> +			.a3 = query_uuid.a3,
> +			.a4 = query_uuid.a4,
> +			.a5 = 0,
> +			.a6 = 0,
> +			.a7 = 0,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		int ret;
> +
> +		/*
> +		 * res.a2 contains the count of partition information descriptors
> +		 * populated in the RX buffer
> +		 */
> +		if (res.a2) {
> +			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
> +			if (ret) {
> +				ffa_err("failed to read partition(s) data , error (%d)", ret);
> +				ffa_release_rx_buffer();
> +				return -EINVAL;
> +			}
> +		}
> +
> +		/*
> +		 * return the SP count (when querying using a UUID)
> +		 */
> +		if (pcount)
> +			*pcount = (u32)res.a2;
> +
> +		/*
> +		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
> +		 * is assigned to the consumer (u-boot). So, we need to give
> +		 * the ownership back to the SPM or hypervisor
> +		 */
> +		ret = ffa_release_rx_buffer();
> +
> +		return ret;
> +	}
> +
> +	ffa_errno = (int)res.a2;
> +	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
> + *
> + * The passed arguments:
> + * Mode 1: When getting from the driver the number of
> + *	secure partitions:
> + *	@uuid_str: pointer to the UUID string
> + *	@parts_size: pointer to the variable that contains the number of partitions
> + *			 The variable will be set by the driver
> + *	@buffer: NULL
> + *
> + * Mode 2: When requesting the driver to return the
> + *	partitions information:
> + *	@uuid_str: pointer to the UUID string
> + *	@parts_size: pointer to the size of the SPs information buffer in bytes
> + *	@buffer: pointer to SPs information buffer
> + *		(allocated by the client).
> + *		The buffer will be filled by the driver
> + *
> + * This is the boot time function that queries the secure partition data from
> + * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
> + * FF-A function to query the partition information from secure world.
> + *
> + * A client of the FF-A driver should know the UUID of the service it wants to
> + * access. It should use the UUID to request the FF-A driver to provide the
> + * partition(s) information of the service. The FF-A driver uses
> + * PARTITION_INFO_GET to obtain this information. This is implemented through
> + * ffa_get_partitions_info function.
> + * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
> + * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
> + * They are not saved (already done). We only update the UUID in the cached area.
> + * This assumes that partitions data does not change in the secure world.
> + * Otherwise u-boot will have an outdated partition data. The benefit of caching
> + * the information in the FF-A driver is to accommodate discovery after
> + * ExitBootServices().
> + *
> + * When invoked through a client request, ffa_get_partitions_info should be
> + * called twice. First call is to get from the driver the number of secure
> + * partitions (SPs) associated to a particular UUID.
> + * Then, the caller (client) allocates the buffer to host the SPs data and
> + * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
> + * buffer.
> + *
> + * To achieve the mechanism described above, ffa_get_partitions_info uses the
> + * following functions:
> + *		ffa_read_partitions_info
> + *		ffa_query_partitions_info
> + *
> + * Return:
> + *
> + * @parts_size: When pointing to the number of partitions variable, the number is
> + * set by the driver.
> + * When pointing to the partitions information buffer size, the buffer will be
> + * filled by the driver.
> + *
> + * On success 0 is returned. Otherwise, failure
> + */
> +static int ffa_get_partitions_info(const char *uuid_str,
> +				   u32 *parts_size, struct ffa_partition_info *buffer)
> +{
> +	/*
> +	 * fill_data:
> +	 * 0: return the SP count
> +	 * 1: fill SP data and return it to the caller
> +	 * -1: undefined mode
> +	 */
> +	int fill_data = -1;
> +	u32 desc_idx, client_desc_idx;
> +	struct ffa_partition_uuid part_uuid = {0};
> +	u32 client_desc_max_cnt;
> +	u32 parts_found = 0;
> +
> +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
> +		ffa_err("no partition installed");
> +		return -EINVAL;
> +	}
> +
> +	if (!uuid_str) {
> +		ffa_err("no UUID provided");
> +		return -EINVAL;
> +	}
> +
> +	if (!parts_size) {
> +		ffa_err("no size/count provided");
> +		return -EINVAL;
> +	}
> +
> +	if (be_uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
> +		ffa_err("invalid UUID");
> +		return -EINVAL;
> +	}
> +
> +	if (!buffer) {
> +		/* Mode 1: getting the number of secure partitions */
> +
> +		fill_data = 0;
> +
> +		ffa_info("Preparing for checking partitions count");
> +
> +	} else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
> +		   !(*parts_size % sizeof(struct ffa_partition_info))) {
> +		/* Mode 2: retrieving the partitions information */
> +
> +		fill_data = 1;
> +
> +		client_desc_idx = 0;
> +
> +		/*
> +		 * number of empty descriptors preallocated by the caller
> +		 */
> +		client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
> +
> +		ffa_info("Preparing for filling partitions info");
> +
> +	} else {
> +		ffa_err("invalid function arguments provided");
> +		return -EINVAL;
> +	}
> +
> +	ffa_info("Searching partitions using the provided UUID");
> +
> +	/*
> +	 * search in the cached partitions
> +	 */
> +	for (desc_idx = 0;
> +	     desc_idx < ffa_priv_data->partitions.count;
> +	     desc_idx++) {
> +		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
> +					   &part_uuid)) {
> +			ffa_info("Partition ID %x matches the provided UUID",
> +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> +
> +			parts_found++;
> +
> +			if (fill_data) {
> +				/*
> +				 * trying to fill the partition info in the input buffer
> +				 */
> +
> +				if (client_desc_idx < client_desc_max_cnt) {
> +					buffer[client_desc_idx++] =
> +						ffa_priv_data->partitions.descs[desc_idx].info;
> +					continue;
> +				}
> +
> +				ffa_err("failed to fill the current descriptor client buffer full");
> +				return -ENOBUFS;
> +			}
> +		}
> +	}
> +
> +	if (!parts_found) {
> +		int ret;
> +
> +		ffa_info("No partition found. Querying framework ...");
> +
> +		ret = ffa_query_partitions_info(&part_uuid, &parts_found);
> +
> +		if (ret == 0) {
> +			if (!fill_data) {
> +				*parts_size = parts_found;
> +
> +				ffa_info("Number of partition(s) found matching the UUID: %d",
> +					 parts_found);
> +			} else {
> +				/*
> +				 * If SPs data detected, they are already in the private data
> +				 * structure, retry searching SP data again to return them
> +				 *  to the caller
> +				 */
> +				if (parts_found)
> +					ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
> +				else
> +					ret = -ENODATA;
> +			}
> +		}
> +
> +		return ret;
> +	}
> +
> +	/* partition(s) found */
> +	if (!fill_data)
> +		*parts_size = parts_found;
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_cache_partitions_info - Queries and saves all secure partitions data
> + *
> + * This is a boot time function that invokes FFA_PARTITION_INFO_GET FF-A
> + * function to query from secure world all partitions information.
> + *
> + * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
> + * All installed partitions information are returned. We cache them in the
> + * resident private data structure and we keep the UUID field empty
> + * (in FF-A 1.0 UUID is not provided by the partition descriptor)
> + *
> + * This function is called at the device probing level.
> + * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_cache_partitions_info(void)
> +{
> +	return ffa_query_partitions_info(NULL, NULL);
> +}
> +
> +/**
> + * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> + * @dst_part_id: destination partition ID
> + * @msg: pointer to the message data preallocated by the client (in/out)
> + *
> + * This is the runtime function that implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * FF-A functions.
> + *
> + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> + * The response from the secure partition is handled by reading the
> + * FFA_MSG_SEND_DIRECT_RESP arguments.
> + *
> + * The maximum size of the data that can be exchanged is 40 bytes which is
> + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int __ffa_runtime ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
> +		return -EINVAL;
> +
> +	/* No partition installed */
> +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
> +		return -ENODEV;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ),
> +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
> +				PREP_PART_ENDPOINT_ID(dst_part_id),
> +			.a2 = 0,
> +			.a3 = msg->data0,
> +			.a4 = msg->data1,
> +			.a5 = msg->data2,
> +			.a6 = msg->data3,
> +			.a7 = msg->data4,
> +			}, &res);
> +
> +	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
> +		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_RUN),
> +			.a1 = res.a1, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {

How can the caller tell this response apart from a FFA_MSG_SEND_DIRECT_RESP?

> +		/* Message sent with no response */
> +		return 0;
> +	}
> +
> +	if (res.a0 == FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP)) {
> +		/*
> +		 * Message sent with response
> +		 * extract the return data
> +		 */
> +		msg->data0 = res.a3;
> +		msg->data1 = res.a4;
> +		msg->data2 = res.a5;
> +		msg->data3 = res.a6;
> +		msg->data4 = res.a7;
> +
> +		return 0;
> +	}
> +
> +	ffa_errno = (int)res.a2;
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * __arm_ffa_fn_smc - 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 low level SMC assembly function
> + *
> + * Return: void
> + */
> +void __ffa_runtime __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
> +{
> +	arm_smccc_1_2_smc(&args, res);
> +}
> +
> +/**
> + * ffa_set_smc_conduit - Set the SMC conduit
> + *
> + * This boot time function selects the SMC conduit by setting the driver invoke function
> + * to SMC assembly function
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_set_smc_conduit(void)
> +{
> +	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
> +
> +	if (!ffa_priv_data->invoke_ffa_fn) {
> +		ffa_err("failure to set the invoke function");
> +		return -EINVAL;
> +	}
> +
> +	ffa_info("Conduit is SMC");
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_set_bus_ops - Set the bus driver operations
> + *
> + * Setting the driver callbacks.
> + *
> + */
> +static void ffa_set_bus_ops(void)
> +{
> +	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
> +	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
> +	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
> +}
> +
> +/**
> + * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
> + * @dev:	the arm_ffa device
> + *
> + * This boot time function creates the main data structure embedding all the driver data.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_alloc_prvdata(struct udevice *dev)
> +{
> +	if (!dev) {
> +		ffa_err("no udevice found");
> +		return -ENODEV;
> +	}
> +
> +	/* The device is registered with the DM. Let's create the driver main data structure*/
> +
> +	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
> +	if (!ffa_priv_data) {
> +		ffa_err("can not allocate the driver main data structure");
> +		return -ENOMEM;
> +	}
> +
> +	ffa_priv_data->dev = dev;
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_probe - The driver probe function
> + * @dev:	the arm_ffa device
> + *
> + * Probing is done at boot time and triggered by the uclass device discovery.
> + * At probe level the following actions are done:
> + *	- setting the conduit
> + *	- querying the FF-A framework version
> + *	- querying from secure world the u-boot endpoint ID
> + *	- querying from secure world the supported features of FFA_RXTX_MAP
> + *	- mapping the RX/TX buffers
> + *	- querying from secure world all the partitions information
> + *
> + * All data queried from secure world is saved in the resident private data structure.
> + *
> + * The probe will fail if either FF-A framework is not detected or the
> + * FF-A requests are not behaving correctly. This ensures that the
> + * driver is not installed and its operations are not exported to the clients.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_probe(struct udevice *dev)
> +{
> +	int ret;
> +
> +	ret = ffa_alloc_prvdata(dev);
> +	if (ret != 0)
> +		return ret;
> +
> +	ffa_set_bus_ops();
> +
> +	ret = ffa_set_smc_conduit();

What if there's a hypervisor involved and HVC would be expected intead?

> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_get_version();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_get_endpoint_id();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_get_rxtx_map_features();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_map_rxtx_buffers();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_cache_partitions_info();

Why are we saving all the found partitions in a cache? It seems that
FFA_PARTITION_INFO_GET could be called each time when needed instead
without any noticeable overhead. Or is the result cached for some other
reason?

> +	if (ret != 0) {
> +		ffa_free_rxtx_buffers();
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_remove - The driver remove function
> + * @dev:	the arm_ffa device
> + * When the device is about to be removed ,  unmap the RX/TX buffers and free the memory
> + * Return:
> + *
> + * 0 on success.
> + */
> +static int ffa_remove(struct udevice *dev)
> +{
> +	ffa_info("removing the device");
> +
> +	ffa_unmap_rxtx_buffers();
> +
> +	if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
> +		ffa_free_rxtx_buffers();
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_unbind - The driver unbind function
> + * @dev:	the arm_ffa device
> + * After the device is removed and memory freed the device is unbound
> + * Return:
> + *
> + * 0 on success.
> + */
> +static int ffa_unbind(struct udevice *dev)
> +{
> +	ffa_info("unbinding the device , private data already released");
> +
> +	ffa_priv_data = NULL;
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_bus_ops_get - bus driver operations getter
> + *
> + * Return:
> + * This runtime function returns a pointer to the driver operations structure
> + */
> +const struct ffa_bus_ops * __ffa_runtime ffa_bus_ops_get(void)
> +{
> +	return &ffa_priv_data->ffa_ops;
> +}
> +
> +/**
> + * ffa_bus_prvdata_get - bus driver private data getter
> + *
> + * Return:
> + * This boot time function returns a pointer to the main private data structure
> + */
> +struct ffa_prvdata **ffa_bus_prvdata_get(void)
> +{
> +	return &ffa_priv_data;
> +}
> +
> +/**
> + * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
> + *
> + * This boot time function makes sure the FF-A bus is discoverable.
> + * Then, the arm_ffa device is probed and 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.
> + * All FF-A clients should use the arm_ffa device to use the FF-A transport.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_bus_discover(void)
> +{
> +	int ret = 0;
> +
> +	if (!ffa_priv_data)
> +		ret = ffa_device_get();
> +
> +	return ret;
> +}
> +
> +/**
> + * Declaring the arm_ffa driver under UCLASS_FFA
> + */
> +
> +U_BOOT_DRIVER(arm_ffa) = {
> +	.name		= FFA_DRV_NAME,
> +	.id		= UCLASS_FFA,
> +	.probe		= ffa_probe,
> +	.remove		= ffa_remove,
> +	.unbind		= ffa_unbind,
> +};
> diff --git a/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c b/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
> new file mode 100644
> index 0000000000..c76cf2147b
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
> @@ -0,0 +1,94 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include "arm_ffa_prv.h"
> +
> +/**
> + * ffa_copy_runtime_data - copy the private data structure  to the runtime area
> + *
> + * This boot time function copies the arm_ffa driver data structures including
> + *  partitions data to the EFI runtime data section.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +efi_status_t ffa_copy_runtime_data(void)
> +{
> +	efi_status_t efi_ret;
> +	efi_uintn_t prvdata_pages;
> +	efi_uintn_t descs_pages;
> +	struct ffa_prvdata **prvdata = NULL; /* Pointer to the current structure */
> +	struct ffa_prvdata *runtime_prvdata = NULL; /* Pointer to the structure runtime copy */
> +	u64 runtime_descs = 0;
> +
> +	prvdata = ffa_bus_prvdata_get();
> +
> +	printf("INFO: EFI: FFA: prv data area at 0x%llx\n", (u64)prvdata);
> +
> +	/* allocate private data runtime area */
> +
> +	prvdata_pages = efi_size_in_pages(sizeof(struct ffa_prvdata));
> +	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> +				     EFI_RUNTIME_SERVICES_DATA,
> +				     prvdata_pages,
> +				     (u64 *)&runtime_prvdata);

Better to use a temporary u64 instead of casting the pointer.

> +
> +	if (efi_ret != EFI_SUCCESS) {
> +		printf("ERROR: EFI: FFA: allocating runtime data (err: 0x%lx, addr 0x%llx)\n",
> +		       efi_ret, (u64)runtime_prvdata);
> +
> +		return efi_ret;
> +	}
> +
> +	printf("INFO: EFI: FFA: runtime data area at 0x%llx\n", (u64)runtime_prvdata);
> +
> +	if (!runtime_prvdata)
> +		return EFI_INVALID_PARAMETER;
> +
> +	/* allocate the partition data runtime area */
> +
> +	descs_pages = efi_size_in_pages((*prvdata)->partitions.count *
> +					sizeof(struct ffa_partition_desc));
> +	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> +				     EFI_RUNTIME_SERVICES_DATA,
> +				     descs_pages,
> +				     &runtime_descs);
> +
> +	if (efi_ret != EFI_SUCCESS) {
> +		printf("ERROR: EFI: FFA: allocating runtime SPs data (err: 0x%lx, addr 0x%llx)\n",
> +		       efi_ret, runtime_descs);
> +
> +		efi_free_pages((u64)runtime_prvdata, prvdata_pages);
> +
> +		return efi_ret;
> +	}
> +
> +	printf("INFO: EFI: FFA: SPs runtime area at 0x%llx\n", (u64)runtime_descs);
> +
> +	if (!runtime_descs)
> +		return EFI_INVALID_PARAMETER;
> +
> +	*runtime_prvdata = **prvdata;

With this you copy fwk_versien. This field will become out of data if
the kernel driver negotiates a different framework version.

> +
> +	runtime_prvdata->dev = NULL;
> +	runtime_prvdata->ffa_ops.partition_info_get = NULL;
> +	runtime_prvdata->ffa_ops.rxtx_unmap = NULL;
> +	runtime_prvdata->partitions.descs = (struct ffa_partition_desc *)runtime_descs;
> +	runtime_prvdata->pair.rxbuf = 0;
> +	runtime_prvdata->pair.txbuf = 0;
> +
> +	/*
> +	 * Update the private data structure pointer in the driver
> +	 * no need to free the old structure. devm takes care of that
> +	 */
> +	*prvdata = runtime_prvdata;
> +
> +	printf("INFO: EFI: FFA: runtime prv data now at 0x%llx , SPs count %d\n",
> +	       (u64)*prvdata, (*prvdata)->partitions.count);
> +
> +	return 0;
> +}
> diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> new file mode 100644
> index 0000000000..f17b100497
> --- /dev/null
> +++ b/include/arm_ffa.h
> @@ -0,0 +1,127 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#ifndef __ARM_FFA_H
> +#define __ARM_FFA_H
> +
> +#include <linux/printk.h>
> +
> +/*
> + * This header is public. It can be used by clients to access
> + * data structures and definitions they need
> + */
> +
> +/*
> + * Macros for displaying logs
> + */
> +
> +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> +
> +/*
> + * struct ffa_partition_info - Partition information descriptor
> + * @id:	Partition ID
> + * @exec_ctxt:	Execution context count
> + * @properties:	Partition properties
> + *
> + * Data structure containing information about partitions instantiated in the system
> + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> + */
> +struct  __packed ffa_partition_info {
> +	u16 id;
> +	u16 exec_ctxt;
> +/* partition supports receipt of direct requests */
> +#define FFA_PARTITION_DIRECT_RECV	BIT(0)
> +/* partition can send direct requests. */
> +#define FFA_PARTITION_DIRECT_SEND	BIT(1)
> +/* partition can send and receive indirect messages. */
> +#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
> +	u32 properties;
> +};
> +
> +/*
> + * struct ffa_send_direct_data - Data structure hosting the data
> + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * @data0-4:	Data read/written from/to x3-x7 registers
> + *
> + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> + * or read from FFA_MSG_SEND_DIRECT_RESP
> + */
> +
> +/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
> +struct __packed ffa_send_direct_data {
> +	unsigned long data0; /* w3/x3 */
> +	unsigned long data1; /* w4/x4 */
> +	unsigned long data2; /* w5/x5 */
> +	unsigned long data3; /* w6/x6 */
> +	unsigned long data4; /* w7/x7 */
> +};
> +
> +#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
> +
> +#include <efi_loader.h>
> +
> +/*
> + *  __ffa_runtime - controls whether functions are
> + * available after calling the EFI ExitBootServices service.
> + * Functions tagged with these keywords are resident (available at boot time and
> + * at runtime)
> + */
> +
> +#define __ffa_runtime_data __efi_runtime_data
> +#define __ffa_runtime __efi_runtime
> +
> +#else
> +
> +/*
> + *  The FF-A driver is independent from EFI
> + */
> +
> +#define __ffa_runtime_data
> +#define __ffa_runtime
> +
> +#endif
> +
> +/**
> + * struct ffa_bus_ops - The driver operations structure
> + * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
> + * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
> + * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
> + *
> + * The data structure providing all the operations supported by the driver.
> + * This structure is EFI runtime resident.
> + */
> +struct ffa_bus_ops {
> +	int (*partition_info_get)(const char *uuid_str,
> +				  u32 *parts_size, struct ffa_partition_info *buffer);
> +	int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg);
> +	int (*rxtx_unmap)(void);
> +};
> +
> +/**
> + * The device driver and the Uclass driver public functions
> + */
> +
> +/**
> + * ffa_bus_ops_get - driver operations getter
> + */
> +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
> + */
> +int ffa_bus_discover(void);
> +
> +#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
> +
> +/**
> + * ffa_copy_runtime_data - copy the private data structure and the SPs data to the runtime area
> + */
> +efi_status_t ffa_copy_runtime_data(void);
> +
> +#endif
> +
> +#endif
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index a432e43871..5dd698b7a9 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -4,6 +4,9 @@
>   *
>   * (C) Copyright 2012
>   * Pavel Herrmann <morpheus.ibis@gmail.com>
> + *
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #ifndef _DM_UCLASS_ID_H
> @@ -55,6 +58,7 @@ enum uclass_id {
>  	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
>  	UCLASS_ETH,		/* Ethernet device */
>  	UCLASS_ETH_PHY,		/* Ethernet PHY device */
> +	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
>  	UCLASS_FIRMWARE,	/* Firmware */
>  	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
>  	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index 6f7333638a..af0b0f3db1 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -3,6 +3,9 @@
>   * EFI application boot time services
>   *
>   * Copyright (c) 2016 Alexander Graf
> + *
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #include <common.h>
> @@ -23,6 +26,10 @@
>  #include <asm/setjmp.h>
>  #include <linux/libfdt_env.h>
>  
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
> +#include <arm_ffa.h>
> +#endif
> +
>  DECLARE_GLOBAL_DATA_PTR;
>  
>  /* Task priority level */
> @@ -2178,6 +2185,14 @@ 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)
> +		/* 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");
> +		else
> +			debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
> +#endif
> +
>  	/* Patch out unsupported runtime function */
>  	efi_runtime_detach();
>  
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v5 04/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-10-03  8:49                                     ` Jens Wiklander
@ 2022-10-03 15:22                                       ` Tom Rini
  2022-10-14 10:40                                         ` Abdellatif El Khlifi
  2022-10-14 10:28                                       ` Abdellatif El Khlifi
  1 sibling, 1 reply; 478+ messages in thread
From: Tom Rini @ 2022-10-03 15:22 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, ilias.apalodimas, nd, sjg, u-boot, vishnu.banavath,
	xueliang.zhong, Heinrich Schuchardt, Jens Wiklander

[-- Attachment #1: Type: text/plain, Size: 1200 bytes --]

On Mon, Oct 03, 2022 at 10:49:23AM +0200, Jens Wiklander wrote:
> On Mon, Sep 26, 2022 at 03:08:21PM +0100, Abdellatif El Khlifi wrote:
[snip]
> > diff --git a/doc/README.ffa.drv b/doc/README.ffa.drv
> > new file mode 100644
> > index 0000000000..1c0a33deb8
> > --- /dev/null
> > +++ b/doc/README.ffa.drv
> > @@ -0,0 +1,160 @@
> > +Arm FF-A Driver
> > +====================
> > +
> > +Introduction
> > +--------------------
> > +
> > +FF-A stands for Firmware Framework for Arm A-profile processors.
> > +
> > +FF-A specifies interfaces that enable a pair of software sandboxes to communicate with each other. A sandbox aka partition could
> > +be a VM in the Normal or Secure world, an application in S-EL0, or a Trusted OS in S-EL1.
> 
> These lines are a bit long, from the coding guide lines:
> The preferred limit on the length of a single line is 80 columns.

Line length isn't a huge problem, we follow what the linux kernel allows
these days.  But, this needs to be in proper sphinx format, under
doc/arch perhaps (unless Heinrich has another idea) and 'make htmldocs'
must pass (I see a lot of formatting errors that will get tripped up on
and fail).

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v6 00/10] introduce Arm FF-A support
  2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                     ` (9 preceding siblings ...)
  2022-09-26 14:08                                   ` [PATCH v5 10/10] arm_ffa: corstone1000: enable EFI " Abdellatif El Khlifi
@ 2022-10-13 10:38                                   ` Abdellatif El Khlifi
  2022-10-13 10:38                                     ` [PATCH v6 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                       ` (11 more replies)
  10 siblings, 12 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-13 10:38 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong, Drew.Reed,
	Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [6].

FF-A describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World. These interfaces enable a pair of
software sandboxes to communicate with each other. A sandbox aka partition could
be a VM in the Normal or Secure world, an application in S-EL0, or a
Trusted OS in S-EL1.

The FF-A transport is implemented as a data bus and a core driver is provided.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

- Discover the presence of secure partitions (SPs) of interest
- Access an SP's service through communication protocols
  e.g. EFI MM communication protocol

The FF-A support provides the following features:

- Being generic by design and can be used by any Arm 64-bit platform
- The FF-A core driver
- The FF-A bus is discoverable on demand at runtime
- The driver provides callbacks to be used by clients to access the FF-A bus
- FF-A driver can be compiled and used without EFI
- Support for SMCCCv1.2 x0-x17 registers
- A new command called armffa is provided as an example of how to access the
  FF-A bus
- An FF-A Sandbox driver is provided with test cases
- Support for FF-A MM communication
- Enabling FF-A and MM communication in Corstone1000 platform

For more details about the FF-A core driver please refer to [7].

Please find at [8] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of the major changes:
===========================

v6:

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://developer.arm.com/documentation/den0077/latest/
[7]: doc/arch/arm64.ffa.rst
[8]: example of boot logs when enabling FF-A

```
U-Boot 2022.07 (Jul 11 2022 - 13:42:58 +0000) corstone1000 aarch64
...
Hit any key to stop autoboot:  0 
...
[FFA] Conduit is SMC                                                                                                                                                                                                                         
[FFA] FF-A driver 1.0
FF-A framework 1.0
[FFA] Versions are compatible 
[FFA] endpoint ID is 0
[FFA] Using 1 4KB page(s) for RX/TX buffers size
[FFA] RX buffer at virtual address 0xfdf1b000
[FFA] TX buffer at virtual address 0xfdf1d000
[FFA] RX/TX buffers mapped
[FFA] Reading partitions data from the RX buffer
[FFA] Partition ID 8001 : info cached
[FFA] Partition ID 8002 : info cached
[FFA] Partition ID 8003 : info cached
[FFA] 3 partition(s) found and cached
[FFA] Preparing for checking partitions count
[FFA] Searching partitions using the provided UUID
[FFA] No partition found. Querying framework ...
[FFA] Reading partitions data from the RX buffer
[FFA] Number of partition(s) found matching the UUID: 1
EFI: Pre-allocating 1 partition(s) info structures
[FFA] Preparing for filling partitions info
[FFA] Searching partitions using the provided UUID
[FFA] Partition ID 8003 matches the provided UUID
EFI: MM partition ID 0x8003
...
EFI stub: Booting Linux Kernel...
...
EFI stub: Exiting boot services...
[FFA] Freeing RX/TX buffers
Booting Linux on physical CPU 0x0000000000 [0x411fd040]
```

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>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Vishnu Banavath <vishnu.banavath@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (10):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce be_uuid_str_to_le_bin function
  arm_ffa: introduce Arm FF-A low-level driver
  arm_ffa: efi: unmap RX/TX buffers
  arm_ffa: introduce armffa command
  arm_ffa: introduce the FF-A Sandbox driver
  arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   11 +
 arch/arm/cpu/armv8/smccc-call.S               |   53 +
 arch/arm/lib/asm-offsets.c                    |   14 +
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    2 +
 cmd/armffa.c                                  |  242 +++
 configs/corstone1000_defconfig                |    4 +
 configs/sandbox64_defconfig                   |    2 +
 configs/sandbox_defconfig                     |    2 +
 doc/arch/arm64.ffa.rst                        |  207 +++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox.rst                          |    1 +
 drivers/Kconfig                               |    2 +
 drivers/Makefile                              |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   36 +
 drivers/firmware/arm-ffa/Makefile             |    7 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     |   16 +
 drivers/firmware/arm-ffa/arm_ffa_prv.h        |  201 +++
 drivers/firmware/arm-ffa/core.c               | 1351 +++++++++++++++++
 drivers/firmware/arm-ffa/sandbox.c            |  659 ++++++++
 .../firmware/arm-ffa/sandbox_arm_ffa_prv.h    |  144 ++
 include/arm_ffa.h                             |   93 ++
 include/configs/corstone1000.h                |    9 +
 include/dm/uclass-id.h                        |    4 +
 include/linux/arm-smccc.h                     |   43 +
 include/mm_communication.h                    |    5 +
 include/sandbox_arm_ffa.h                     |   91 ++
 include/uuid.h                                |    8 +
 lib/efi_loader/Kconfig                        |   14 +-
 lib/efi_loader/efi_boottime.c                 |   15 +
 lib/efi_loader/efi_variable_tee.c             |  264 +++-
 lib/uuid.c                                    |   64 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   40 +
 test/dm/Makefile                              |    2 +
 test/dm/ffa.c                                 |  394 +++++
 36 files changed, 4008 insertions(+), 6 deletions(-)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/firmware/arm-ffa/core.c
 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/arm_ffa.h
 create mode 100644 include/sandbox_arm_ffa.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v6 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
@ 2022-10-13 10:38                                     ` Abdellatif El Khlifi
  2022-10-24 14:19                                       ` Jens Wiklander
  2022-10-13 10:38                                     ` [PATCH v6 02/10] lib: uuid: introduce be_uuid_str_to_le_bin function Abdellatif El Khlifi
                                                       ` (10 subsequent siblings)
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-13 10:38 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong, Drew.Reed

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

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>

---

Changelog:
===============

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

arch/arm/cpu/armv8/smccc-call.S | 53 +++++++++++++++++++++++++++++++++
 arch/arm/lib/asm-offsets.c      | 14 +++++++++
 include/linux/arm-smccc.h       | 43 ++++++++++++++++++++++++++
 3 files changed, 110 insertions(+)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..ec6f299bc9 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
@@ -45,3 +47,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 22fd541f9a..1bc2d90faa 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,9 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -117,6 +120,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+	#ifdef CONFIG_ARM64
+		DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+		DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+		DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+		DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+		DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+		DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+		DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+		DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+		DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+	#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..9105031d55 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +72,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v6 02/10] lib: uuid: introduce be_uuid_str_to_le_bin function
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2022-10-13 10:38                                     ` [PATCH v6 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2022-10-13 10:38                                     ` Abdellatif El Khlifi
  2022-10-24 12:07                                       ` Ilias Apalodimas
  2022-10-13 10:38                                     ` [PATCH v6 03/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
                                                       ` (9 subsequent siblings)
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-13 10:38 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong, Drew.Reed

convert big endian UUID string to little endian buffer

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>

---

Changelog:
===============

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

include/uuid.h |  8 +++++++
 lib/uuid.c     | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..ad3af350f9 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,8 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +46,10 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * be_uuid_str_to_le_bin - Converts a big endian UUID string to a little endian buffer
+ */
+int be_uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 465e1ac38f..15a9ab49d5 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -346,6 +348,68 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * be_uuid_str_to_le_bin - Converts a big endian UUID string to a little endian buffer
+ * @uuid_str:	UUID string in big endian format (36 bytes wide + '/0')
+ * @uuid_bin:	preallocated 16 bytes UUID buffer in little endian format
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ * be		     be	     be	      be      be
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a binary UUID, these endianness rules apply:
+ *     be: means the field in the string is considered a big endian hex number
+ *	   and should be converted to little endian binary format
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int be_uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16 = 0;
+	u32 tmp32 = 0;
+	u64 tmp64 = 0;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp32 = simple_strtoul(uuid_str, NULL, 16);
+	memcpy(uuid_bin, &tmp32, 4);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 9, NULL, 16);
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 14, NULL, 16);
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp16 = simple_strtoul(uuid_str + 19, NULL, 16);
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	/*
+	 * reverse bytes from big to little endian
+	 */
+	tmp64 = simple_strtoull(uuid_str + 24, NULL, 16);
+	memcpy(uuid_bin + 10, (char *)&tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v6 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2022-10-13 10:38                                     ` [PATCH v6 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2022-10-13 10:38                                     ` [PATCH v6 02/10] lib: uuid: introduce be_uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2022-10-13 10:38                                     ` Abdellatif El Khlifi
  2022-10-25  9:31                                       ` Jens Wiklander
  2022-10-13 10:38                                     ` [PATCH v6 04/10] arm_ffa: efi: unmap RX/TX buffers Abdellatif El Khlifi
                                                       ` (8 subsequent siblings)
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-13 10:38 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong, Drew.Reed

Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
and FFA_MSG_SEND_DIRECT_{REQ, RESP}.

In u-boot FF-A design, FF-A is considered as a discoverable bus.
The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- partition_info_get
- sync_send_receive
- rxtx_unmap

[1]: https://developer.arm.com/documentation/den0077/latest/

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>

---

Changelog:
===============

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the u-boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

 MAINTAINERS                               |    7 +
 doc/arch/arm64.ffa.rst                    |  207 ++++
 doc/arch/index.rst                        |    1 +
 drivers/Kconfig                           |    2 +
 drivers/Makefile                          |    1 +
 drivers/firmware/arm-ffa/Kconfig          |   30 +
 drivers/firmware/arm-ffa/Makefile         |    6 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c |   16 +
 drivers/firmware/arm-ffa/arm_ffa_prv.h    |  196 +++
 drivers/firmware/arm-ffa/core.c           | 1337 +++++++++++++++++++++
 include/arm_ffa.h                         |   93 ++
 include/dm/uclass-id.h                    |    4 +
 12 files changed, 1900 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/firmware/arm-ffa/core.c
 create mode 100644 include/arm_ffa.h

diff --git a/MAINTAINERS b/MAINTAINERS
index a26b36c7c2..496f47a516 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -248,6 +248,13 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	doc/arch/arm64.ffa.rst
+F:	drivers/firmware/arm-ffa/
+F:	include/arm_ffa.h
+
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..e98d2cf2b3
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,207 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Driver
+===============
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software sandboxes to
+communicate with each other. A sandbox aka partition could
+be a VM in the Normal or Secure world, an application in S-EL0, or a
+Trusted OS in S-EL1.
+
+This FF-A driver implements the interfaces to communicate with partitions in
+the Secure world aka Secure partitions (SPs).
+
+The driver specifically focuses on communicating with SPs that isolate portions
+of EFI runtime services that must run in a protected environment which is
+inaccessible by the Host OS or Hypervisor. Examples of such services are
+set/get variables.
+
+FF-A driver uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the driver relies on FF-A specification v1.0
+and uses SMC32 calling convention.
+
+At this stage we only need the FF-A v1.0 features.
+
+The driver has been tested with Optee OS which supports SMC32 for most of
+the SMC ABIs.
+
+For more details please refer to the FF-A v1.0 spec:
+https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
+
+For more details please refer to the SMC Calling Convention v1.2 spec:
+https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+CONFIG_ARM_FFA_TRANSPORT
+    Enables the FF-A bus driver. Turn this on if you want to use FF-A
+    communication.
+
+CONFIG_SANDBOX_FFA
+    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
+    Sandbox and provides functional tests for FF-A.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction
+is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-boot FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs in the driver.
+
+FF-A bus discovery in U-boot
+-------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is discovered on
+demand by the clients (users).
+
+Clients can discover the FF-A bus using ffa_bus_discover() API which triggers the
+discovery process.
+
+ffa_bus_discover() creates, binds and probes the arm_ffa device using
+device_{bind, probe} APIs.
+
+The discovery process consists in communicating with secure world (or hypervisor)
+and querying specific data.
+
+The discovery process takes place during the arm_ffa device probing which is
+handled by ffa_probe().
+
+The FF-A bus discovery is successful and the bus is ready for use when these
+operations succeed:
+
+- querying the FF-A framework version
+- querying from secure world the U-boot endpoint ID
+- querying from secure world the RX/TX mapping  features
+- mapping the RX/TX buffers
+- querying from secure world all the partitions information
+
+Discovery failure results in a probing failure and the arm_ffa device is
+destroyed.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must:
+
+- Query SPs in EFI boot time mode using the service UUID.
+- Unmap RX/TX buffers before EFI runtime mode starts.
+
+The RX/TX buffers are only available at EFI boot time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped by the user before EFI runtime mode
+starts. The driver provides a bus operation for that: rxtx_unmap()
+
+If  RX/TX buffers created by U-boot are not unmapped and by
+consequence becoming available at EFI runtime, secure world will get confused
+about RX/TX buffers ownership (U-boot vs kernel).
+
+The bus driver layer
+------------------------------
+
+The driver comes on top of the SMCCC layer and is implemented in
+drivers/firmware/arm-ffa/core.c
+
+The driver provides the following features:
+
+- Support for the 32-bit version of the following ABIs:
+
+FFA_VERSION
+FFA_ID_GET
+FFA_FEATURES
+FFA_PARTITION_INFO_GET
+FFA_RXTX_UNMAP
+FFA_RX_RELEASE
+FFA_RUN
+FFA_ERROR
+FFA_SUCCESS
+FFA_INTERRUPT
+
+- Support for the 64-bit version of the following ABIs:
+
+FFA_RXTX_MAP
+FFA_MSG_SEND_DIRECT_REQ
+FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, the driver takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- The driver provides callbacks to be used by clients to access the FF-A bus:
+
+partition_info_get
+sync_send_receive
+rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+Using armffa command
+-----------------------------------
+
+armffa is a command showcasing how to use the FF-A driver and how to invoke
+its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus
+interfaces.
+
+Usage:
+
+armffa <sub-command> <arguments>
+
+sub-commands:
+
+        getpart <partition UUID>
+
+            lists the partition(s) info
+
+        ping <partition ID>
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays the arm_ffa device info
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index 792d9182c3..8d1ab0ad4e 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 8b6fead351..b06b1ae481 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
 
 source "drivers/adc/Kconfig"
 
+source "drivers/firmware/arm-ffa/Kconfig"
+
 source "drivers/ata/Kconfig"
 
 source "drivers/axi/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 9d9f69a3c9..bf8d7b8cfc 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -111,6 +111,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..f1427535f9
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,30 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  This driver is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In u-boot FF-A design, FF-A is considered as a discoverable bus.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  This FF-A driver takes care of all the interactions between Normal world
+	  and Secure World.
+
+	  For more details about the FF-A driver, please refer to doc/README.ffa.drv
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..043a8915be
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2022
+# Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com.
+
+obj-y += arm-ffa-uclass.o core.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..7d9695d289
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+UCLASS_DRIVER(ffa) = {
+	.name		= "ffa",
+	.id		= UCLASS_FFA,
+};
diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
new file mode 100644
index 0000000000..7bc90f7f66
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <arm_ffa.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/arm-smccc.h>
+
+/*
+ * This header is private. It is exclusively used by the FF-A driver
+ */
+
+/* FF-A core driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* FF-A driver version definitions */
+
+#define MAJOR_VERSION_MASK		GENMASK(30, 16)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/*
+ * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
+ */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR					= 0x60,
+	FFA_SUCCESS					= 0x61,
+	FFA_INTERRUPT				= 0x62,
+	FFA_VERSION					= 0x63,
+	FFA_FEATURES				= 0x64,
+	FFA_RX_RELEASE				= 0x65,
+	FFA_RXTX_MAP				= 0x66,
+	FFA_RXTX_UNMAP			= 0x67,
+	FFA_PARTITION_INFO_GET		= 0x68,
+	FFA_ID_GET					= 0x69,
+	FFA_RUN						= 0x6D,
+	FFA_MSG_SEND_DIRECT_REQ	= 0x6F,
+	FFA_MSG_SEND_DIRECT_RESP	= 0x70,
+
+	/* to be updated when adding new FFA IDs */
+	FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
+	FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
+};
+
+/* number of the errors supported by the FF-A specification */
+#define MAX_NUMBER_FFA_ERR 9
+
+/* container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#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
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Data structure hosting the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	u64 rxbuf; /* virtual address */
+	u64 txbuf; /* virtual address */
+	size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * This data structure contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* virtual address */
+};
+
+/**
+ * struct ffa_prvdata - the driver private data structure
+ *
+ * @dev:	The arm_ffa device under u-boot driver model
+ * @ffa_ops:	The driver operations structure
+ * @fwk_version:	FF-A framework version
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ * @invoke_ffa_fn:	The function executing the FF-A function
+ *
+ * The driver data structure hosting all resident data.
+ */
+struct ffa_prvdata {
+	struct udevice *dev;
+	struct ffa_bus_ops ffa_ops;
+	u32 fwk_version;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+	invoke_ffa_fn_t invoke_ffa_fn;
+};
+
+/**
+ * ffa_device_get - create, bind and probe the arm_ffa device
+ */
+int ffa_device_get(void);
+
+/**
+ * ffa_bus_prvdata_get - bus driver private data getter
+ */
+struct ffa_prvdata **ffa_bus_prvdata_get(void);
+
+#endif
diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
new file mode 100644
index 0000000000..324367d12b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/core.c
@@ -0,0 +1,1337 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include "arm_ffa_prv.h"
+#include <asm/global_data.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * The device private data structure containing all the
+ * data read from secure world
+ */
+struct ffa_prvdata *ffa_priv_data;
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	0,
+	-EOPNOTSUPP,	/* NOT_SUPPORTED */
+	-EINVAL,	/* INVALID_PARAMETERS */
+	-ENOMEM,	/* NO_MEMORY */
+	-EBUSY,		/* BUSY */
+	-EINTR,		/* INTERRUPTED */
+	-EACCES,	/* DENIED */
+	-EAGAIN,	/* RETRY */
+	-ECANCELED,	/* ABORTED */
+};
+
+struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			"",
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+			"", /* INVALID_PARAMETERS */
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"", /* DENIED */
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			"",
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			"", /* INVALID_PARAMETERS */
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"", /* DENIED */
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			"",
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+			"", /* INVALID_PARAMETERS */
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"", /* DENIED */
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			"",
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			"BUSY: RX buffer of the caller is not free",
+			"", /* INTERRUPTED */
+			"DENIED: Callee is not in a state to handle this request",
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+			{
+			"",
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"", /* DENIED */
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+			{
+			"",
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			"", /* INVALID_PARAMETERS */
+			"", /* NO_MEMORY */
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"DENIED: Caller did not have ownership of the RX buffer",
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+			{
+			"",
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			"NO_MEMORY: Not enough memory",
+			"", /* BUSY */
+			"", /* INTERRUPTED */
+			"DENIED: Buffer pair already registered",
+			"", /* RETRY */
+			"", /* ABORTED */
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This function maps the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This function maps the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str || !err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/*
+ * Driver core functions
+ */
+
+/**
+ * ffa_remove_device - removes the arm_ffa device
+ * @dev:	the device to be removed
+ *
+ * This function makes sure the arm_ffa device is removed
+ * No need to free the kmalloced data when the device is destroyed.
+ * It's automatically done by devm management by
+ * device_remove() -> device_free() -> devres_release_probe().
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_remove_device(struct udevice *dev)
+{
+	int ret;
+
+	if (!dev) {
+		ffa_err("no udevice found");
+		return -ENODEV;
+	}
+
+	ret = device_remove(dev, DM_REMOVE_NORMAL);
+	if (ret) {
+		ffa_err("unable to remove. err:%d\n", ret);
+		return ret;
+	}
+
+	ffa_info("device removed and freed");
+
+	ret = device_unbind(dev);
+	if (ret) {
+		ffa_err("unable to unbind. err:%d\n", ret);
+		return ret;
+	}
+
+	ffa_info("device unbound");
+
+	return 0;
+}
+
+/**
+ * ffa_device_get - create, bind and probe the arm_ffa device
+ *
+ * This function makes sure the arm_ffa device is
+ * created, bound to this driver, probed and ready to use.
+ * Arm FF-A transport is implemented through a single u-boot
+ * device managing the FF-A bus (arm_ffa).
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_device_get(void)
+{
+	int ret;
+	struct udevice *dev = NULL;
+
+	ret = device_bind(dm_root(),
+			  DM_DRIVER_GET(arm_ffa),
+			  FFA_DRV_NAME,
+			  NULL,
+			  ofnode_null(),
+			  &dev);
+	if (ret)
+		return ret;
+
+	/* The FF-A bus discovery succeeds when probing is successful */
+	ret = device_probe(dev);
+	if (ret) {
+		ffa_err("arm_ffa device probing failed");
+		ffa_remove_device(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_version - FFA_VERSION handler function
+ *
+ * This function implements FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_version(void)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION),
+			.a1 = FFA_VERSION_1_0
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
+		ffa_info("Versions are compatible ");
+
+		ffa_priv_data->fwk_version = res.a0;
+
+		return 0;
+	}
+
+	ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id - FFA_ID_GET handler function
+ *
+ * This function implements FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET)
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		ffa_info("endpoint ID is %u", ffa_priv_data->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * This function sets the minimum number of pages
+ *  in each of the RX/TX buffers in the private data structure
+ *
+ * Return:
+ *
+ * buf_4k_pages points to the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
+{
+	if (!ffa_priv_data)
+		return -EINVAL;
+
+	switch (prop_field) {
+	case RXTX_4K:
+		ffa_priv_data->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		ffa_priv_data->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		ffa_priv_data->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		ffa_err("RX/TX buffer size not supported");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ *
+ * This function implements FFA_FEATURES FF-A function
+ * to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP)
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt((u32)res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers - frees the RX/TX buffers
+ *
+ * This  function  frees the RX/TX buffers
+ *
+ */
+static void ffa_free_rxtx_buffers(void)
+{
+	ffa_info("Freeing RX/TX buffers");
+
+	if (ffa_priv_data->pair.rxbuf) {
+		free((void *)ffa_priv_data->pair.rxbuf);
+		ffa_priv_data->pair.rxbuf = 0;
+	}
+
+	if (ffa_priv_data->pair.txbuf) {
+		free((void *)ffa_priv_data->pair.txbuf);
+		ffa_priv_data->pair.txbuf = 0;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
+ *
+ * This function is used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(void)
+{
+	u64 bytes;
+
+	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
+		 ffa_priv_data->pair.rxtx_min_pages);
+
+	bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 */
+
+	ffa_priv_data->pair.rxbuf = (u64)memalign(bytes, bytes);
+	if (!ffa_priv_data->pair.rxbuf) {
+		ffa_err("failure to allocate RX buffer");
+		return -ENOBUFS;
+	}
+
+	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
+
+	ffa_priv_data->pair.txbuf = (u64)memalign(bytes, bytes);
+	if (!ffa_priv_data->pair.txbuf) {
+		free((void *)ffa_priv_data->pair.rxbuf);
+		ffa_priv_data->pair.rxbuf = 0;
+		ffa_err("failure to allocate the TX buffer");
+		return -ENOBUFS;
+	}
+
+	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
+
+	/*
+	 * make sure the buffers are cleared before use
+	 */
+	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
+	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
+ *
+ * This function implements FFA_RXTX_MAP FF-A function
+ * to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers(void)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ret = ffa_alloc_rxtx_buffers();
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 *no need to convert from virtual to physical
+	 */
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = ffa_priv_data->pair.txbuf,
+			.a2 = ffa_priv_data->pair.rxbuf,
+			.a3 = ffa_priv_data->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_info("RX/TX buffers mapped");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers();
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_unmap_rxtx_buffers(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id)
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers();
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
+ *
+ * This function invokes FFA_RX_RELEASE FF-A function
+ * to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE)
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical - checks whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * This function is used by ffa_read_partitions_info to search
+ * for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+int ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+			   const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
+ *							and saves it in the private structure
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * This function reads the partitions information
+ * returned by the FFA_PARTITION_INFO_GET and saves it in the private
+ * data structure.
+ *
+ * Return:
+ *
+ * The private data structure is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
+{
+	if (!count) {
+		ffa_err("no partition detected");
+		return -ENODATA;
+	}
+
+	ffa_info("Reading partitions data from the RX buffer");
+
+	if (!part_uuid) {
+		/*
+		 * querying information of all partitions
+		 */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			ffa_err("partitions data size exceeds the RX buffer size:");
+			ffa_err("    sizes in bytes: data %llu , RX buffer %llu ",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		ffa_priv_data->partitions.descs = devm_kmalloc(ffa_priv_data->dev, data_bytes,
+							       __GFP_ZERO);
+		if (!ffa_priv_data->partitions.descs) {
+			ffa_err("cannot  allocate partitions data buffer");
+			return -ENOMEM;
+		}
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			ffa_priv_data->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			ffa_info("Partition ID %x : info cached",
+				 ffa_priv_data->partitions.descs[desc_idx].info.id);
+		}
+
+		ffa_priv_data->partitions.count = count;
+
+		ffa_info("%d partition(s) found and cached", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
+
+		/*
+		 * search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/*
+			 * search the current ID in the cached partitions
+			 */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < ffa_priv_data->partitions.count;
+			     cached_desc_idx++) {
+				/*
+				 * save the UUID
+				 */
+				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
+ *
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * This function executes the FFA_PARTITION_INFO_GET
+ * to query the partitions data. Then, it calls ffa_read_partitions_info
+ * to save the data in the private data structure.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
+			if (ret) {
+				ffa_err("failed to read partition(s) data , error (%d)", ret);
+				ffa_release_rx_buffer();
+				return -EINVAL;
+			}
+		}
+
+		/*
+		 * return the SP count (when querying using a UUID)
+		 */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer();
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
+ *
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@uuid_str: pointer to the UUID string
+ *	@parts_size: pointer to the variable that contains the number of partitions
+ *			 The variable will be set by the driver
+ *	@buffer: NULL
+ *
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@uuid_str: pointer to the UUID string
+ *	@parts_size: pointer to the size of the SPs information buffer in bytes
+ *	@buffer: pointer to SPs information buffer
+ *		(allocated by the client).
+ *		The buffer will be filled by the driver
+ *
+ * This function queries the secure partition data from
+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * When invoked through a client request, ffa_get_partitions_info should be
+ * called twice. First call is to get from the driver the number of secure
+ * partitions (SPs) associated to a particular UUID.
+ * Then, the caller (client) allocates the buffer to host the SPs data and
+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
+ * buffer.
+ *
+ * To achieve the mechanism described above, ffa_get_partitions_info uses the
+ * following functions:
+ *		ffa_read_partitions_info
+ *		ffa_query_partitions_info
+ *
+ * Return:
+ *
+ * @parts_size: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer size, the buffer will be
+ * filled by the driver.
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+static int ffa_get_partitions_info(const char *uuid_str,
+				   u32 *parts_size, struct ffa_partition_info *buffer)
+{
+	/*
+	 * fill_data:
+	 * 0: return the SP count
+	 * 1: fill SP data and return it to the caller
+	 * -1: undefined mode
+	 */
+	int fill_data = -1;
+	u32 desc_idx, client_desc_idx;
+	struct ffa_partition_uuid part_uuid = {0};
+	u32 client_desc_max_cnt;
+	u32 parts_found = 0;
+
+	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
+		ffa_err("no partition installed");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		ffa_err("no UUID provided");
+		return -EINVAL;
+	}
+
+	if (!parts_size) {
+		ffa_err("no size/count provided");
+		return -EINVAL;
+	}
+
+	if (be_uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		ffa_err("invalid UUID");
+		return -EINVAL;
+	}
+
+	if (!buffer) {
+		/* Mode 1: getting the number of secure partitions */
+
+		fill_data = 0;
+
+		ffa_info("Preparing for checking partitions count");
+
+	} else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
+		   !(*parts_size % sizeof(struct ffa_partition_info))) {
+		/* Mode 2: retrieving the partitions information */
+
+		fill_data = 1;
+
+		client_desc_idx = 0;
+
+		/*
+		 * number of empty descriptors preallocated by the caller
+		 */
+		client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
+
+		ffa_info("Preparing for filling partitions info");
+
+	} else {
+		ffa_err("invalid function arguments provided");
+		return -EINVAL;
+	}
+
+	ffa_info("Searching partitions using the provided UUID");
+
+	/*
+	 * search in the cached partitions
+	 */
+	for (desc_idx = 0;
+	     desc_idx < ffa_priv_data->partitions.count;
+	     desc_idx++) {
+		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
+					   &part_uuid)) {
+			ffa_info("Partition ID %x matches the provided UUID",
+				 ffa_priv_data->partitions.descs[desc_idx].info.id);
+
+			parts_found++;
+
+			if (fill_data) {
+				/*
+				 * trying to fill the partition info in the input buffer
+				 */
+
+				if (client_desc_idx < client_desc_max_cnt) {
+					buffer[client_desc_idx++] =
+						ffa_priv_data->partitions.descs[desc_idx].info;
+					continue;
+				}
+
+				ffa_err("failed to fill the current descriptor client buffer full");
+				return -ENOBUFS;
+			}
+		}
+	}
+
+	if (!parts_found) {
+		int ret;
+
+		ffa_info("No partition found. Querying framework ...");
+
+		ret = ffa_query_partitions_info(&part_uuid, &parts_found);
+
+		if (ret == 0) {
+			if (!fill_data) {
+				*parts_size = parts_found;
+
+				ffa_info("Number of partition(s) found matching the UUID: %d",
+					 parts_found);
+			} else {
+				/*
+				 * If SPs data detected, they are already in the private data
+				 * structure, retry searching SP data again to return them
+				 *  to the caller
+				 */
+				if (parts_found)
+					ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
+				else
+					ret = -ENODATA;
+			}
+		}
+
+		return ret;
+	}
+
+	/* partition(s) found */
+	if (!fill_data)
+		*parts_size = parts_found;
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info - Queries and saves all secure partitions data
+ *
+ * This function invokes FFA_PARTITION_INFO_GET FF-A
+ * function to query from secure world all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in the
+ * resident private data structure and we keep the UUID field empty
+ * (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * This function is called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(void)
+{
+	return ffa_query_partitions_info(NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
+		return -EINVAL;
+
+	/* No partition installed */
+	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
+		return -ENODEV;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ),
+			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP)) {
+		/*
+		 * Message sent with response
+		 * extract the return data
+		 */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * __arm_ffa_fn_smc - 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 low level SMC assembly function
+ *
+ * Return: void
+ */
+void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * ffa_set_smc_conduit - Set the SMC conduit
+ *
+ * This function selects the SMC conduit by setting the driver invoke function
+ * to SMC assembly function
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_smc_conduit(void)
+{
+	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
+
+	if (!ffa_priv_data->invoke_ffa_fn) {
+		ffa_err("failure to set the invoke function");
+		return -EINVAL;
+	}
+
+	ffa_info("Conduit is SMC");
+
+	return 0;
+}
+
+/**
+ * ffa_set_bus_ops - Set the bus driver operations
+ *
+ * Setting the driver callbacks.
+ *
+ */
+static void ffa_set_bus_ops(void)
+{
+	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
+	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
+	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
+}
+
+/**
+ * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
+ * @dev:	the arm_ffa device
+ *
+ * This function creates the main data structure embedding all the driver data.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_prvdata(struct udevice *dev)
+{
+	if (!dev) {
+		ffa_err("no udevice found");
+		return -ENODEV;
+	}
+
+	/* The device is registered with the DM. Let's create the driver main data structure*/
+
+	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
+	if (!ffa_priv_data) {
+		ffa_err("can not allocate the driver main data structure");
+		return -ENOMEM;
+	}
+
+	ffa_priv_data->dev = dev;
+
+	return 0;
+}
+
+/**
+ * ffa_probe - The driver probe function
+ * @dev:	the arm_ffa device
+ *
+ * Probing is done at boot time and triggered by the uclass device discovery.
+ * At probe level the following actions are done:
+ *	- setting the conduit
+ *	- querying the FF-A framework version
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in the resident private data structure.
+ *
+ * The probe will fail if either FF-A framework is not detected or the
+ * FF-A requests are not behaving correctly. This ensures that the
+ * driver is not installed and its operations are not exported to the clients.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = ffa_alloc_prvdata(dev);
+	if (ret != 0)
+		return ret;
+
+	ffa_set_bus_ops();
+
+	ret = ffa_set_smc_conduit();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_version();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_endpoint_id();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_cache_partitions_info();
+	if (ret != 0) {
+		ffa_free_rxtx_buffers();
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_remove - The driver remove function
+ * @dev:	the arm_ffa device
+ * When the device is about to be removed ,  unmap the RX/TX buffers and free the memory
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_remove(struct udevice *dev)
+{
+	ffa_info("removing the device");
+
+	ffa_unmap_rxtx_buffers();
+
+	if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
+		ffa_free_rxtx_buffers();
+
+	return 0;
+}
+
+/**
+ * ffa_unbind - The driver unbind function
+ * @dev:	the arm_ffa device
+ * After the device is removed and memory freed the device is unbound
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_unbind(struct udevice *dev)
+{
+	ffa_info("unbinding the device , private data already released");
+
+	ffa_priv_data = NULL;
+
+	return 0;
+}
+
+/**
+ * ffa_bus_ops_get - bus driver operations getter
+ *
+ * Return:
+ * This function returns a pointer to the driver operations structure
+ */
+const struct ffa_bus_ops *ffa_bus_ops_get(void)
+{
+	return &ffa_priv_data->ffa_ops;
+}
+
+/**
+ * ffa_bus_prvdata_get - bus driver private data getter
+ *
+ * Return:
+ * This function returns a pointer to the main private data structure
+ */
+struct ffa_prvdata **ffa_bus_prvdata_get(void)
+{
+	return &ffa_priv_data;
+}
+
+/**
+ * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
+ *
+ * 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 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.
+ * All FF-A clients should use the arm_ffa device to use the FF-A transport.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_bus_discover(void)
+{
+	int ret = 0;
+
+	if (!ffa_priv_data)
+		ret = ffa_device_get();
+
+	return ret;
+}
+
+/**
+ * Declaring the arm_ffa driver under UCLASS_FFA
+ */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.probe		= ffa_probe,
+	.remove		= ffa_remove,
+	.unbind		= ffa_unbind,
+};
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..d146e7b328
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * Macros for displaying logs
+ */
+
+#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
+#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct  __packed ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct __packed ffa_send_direct_data {
+	unsigned long data0; /* w3/x3 */
+	unsigned long data1; /* w4/x4 */
+	unsigned long data2; /* w5/x5 */
+	unsigned long data3; /* w6/x6 */
+	unsigned long data4; /* w7/x7 */
+};
+
+/**
+ * struct ffa_bus_ops - The driver operations structure
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(const char *uuid_str,
+				  u32 *parts_size, struct ffa_partition_info *buffer);
+	int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg);
+	int (*rxtx_unmap)(void);
+};
+
+/**
+ * The device driver and the Uclass driver public functions
+ */
+
+/**
+ * ffa_bus_ops_get - driver operations getter
+ */
+const struct ffa_bus_ops *ffa_bus_ops_get(void);
+
+/**
+ * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
+ */
+int ffa_bus_discover(void);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index a432e43871..5dd698b7a9 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,9 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -55,6 +58,7 @@ enum uclass_id {
 	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
 	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v6 04/10] arm_ffa: efi: unmap RX/TX buffers
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                       ` (2 preceding siblings ...)
  2022-10-13 10:38                                     ` [PATCH v6 03/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
@ 2022-10-13 10:38                                     ` Abdellatif El Khlifi
  2022-10-24 12:08                                       ` Ilias Apalodimas
  2022-10-13 10:38                                     ` [PATCH v6 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                       ` (7 subsequent siblings)
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-13 10:38 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong, Drew.Reed

unmap RX/TX buffers at ExitBootServices()

Unmapping the RX/TX buffers created by u-boot is needed before EFI
runtime.

At EFI runtime the linux kernel takes care of allocating its own RX/TX
buffers and registering them with the secure world.

Secure world should be using the RX/TX buffers created by the kernel.
So, RX/TX buffers created by u-boot must be unmapped.

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>
---
 lib/efi_loader/efi_boottime.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index a56021559b..2054b33568 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -3,6 +3,9 @@
  * EFI application boot time services
  *
  * Copyright (c) 2016 Alexander Graf
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -23,6 +26,10 @@
 #include <asm/setjmp.h>
 #include <linux/libfdt_env.h>
 
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+#include <arm_ffa.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Task priority level */
@@ -2178,6 +2185,14 @@ 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)
+		/* 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");
+		else
+			debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
+#endif
+
 	/* Patch out unsupported runtime function */
 	efi_runtime_detach();
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v6 05/10] arm_ffa: introduce armffa command
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                       ` (3 preceding siblings ...)
  2022-10-13 10:38                                     ` [PATCH v6 04/10] arm_ffa: efi: unmap RX/TX buffers Abdellatif El Khlifi
@ 2022-10-13 10:38                                     ` Abdellatif El Khlifi
  2022-10-13 10:38                                     ` [PATCH v6 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
                                                       ` (6 subsequent siblings)
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-13 10:38 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong, Drew.Reed

Provide armffa command showcasing the use of the FF-A driver

The armffa command allows to query secure partitions data from
the secure world and exchanging messages with the partitions.

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>

---

Changelog:
===============

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

 MAINTAINERS                      |   1 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   2 +
 cmd/armffa.c                     | 242 +++++++++++++++++++++++++++++++
 drivers/firmware/arm-ffa/Kconfig |   1 +
 5 files changed, 256 insertions(+)
 create mode 100644 cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 496f47a516..663e2abccd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -251,6 +251,7 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+F:	cmd/armffa.c
 F:	doc/arch/arm64.ffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 6f00bd9307..6b1ffee3cf 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -912,6 +912,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the Arm FF-A driver
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index cf6ce1bd6f..7d806817b1 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,8 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
 obj-$(CONFIG_CMD_AES) += aes.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..9b56e8a830
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <arm_ffa.h>
+#include <asm/io.h>
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+
+/**
+ * do_ffa_get_singular_partition_info - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver partition_info_get operation
+ * to retrieve the data.
+ * The input UUID string is expected to be in big endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_get_singular_partition_info(struct cmd_tbl *cmdtp, int flag, int argc,
+					      char *const argv[])
+{
+	u32 count = 0, size = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	/* Mode 1: getting the number of secure partitions */
+	ret = ffa_bus_ops_get()->partition_info_get(argv[0], &count, NULL);
+	if (ret != 0) {
+		ffa_err("Failure in querying partitions count (error code: %d)", ret);
+		return ret;
+	}
+
+	if (!count) {
+		ffa_info("No secure partition found");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with ffa_partition_info structs
+	 */
+
+	ffa_info("Pre-allocating %d partition(s) info structures", count);
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	size = count * sizeof(struct ffa_partition_info);
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+
+	ret = ffa_bus_ops_get()->partition_info_get(argv[0], &size, parts_info);
+	if (ret != 0) {
+		ffa_err("Failure in querying partition(s) info (error code: %d)", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * SPs found , show the partition information
+	 */
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		ffa_info("Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x",
+			 parts_info[info_idx].id,
+			 parts_info[info_idx].exec_ctxt,
+			 parts_info[info_idx].properties);
+	}
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * do_ffa_msg_send_direct_req - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function sends data to the secure partition which the ID is provided
+ * as an argument. The function uses the arm_ffa driver sync_send_receive operation
+ * to send data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int  do_ffa_msg_send_direct_req(struct cmd_tbl *cmdtp, int flag, int argc,
+				char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	errno = 0;
+	part_id = strtoul(argv[0], NULL, 16);
+
+	if (errno) {
+		ffa_err("Invalid partition ID");
+		return -EINVAL;
+	}
+
+	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
+	if (ret == 0) {
+		u8 cnt;
+
+		ffa_info("SP response:\n[LSB]");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			ffa_info("0x%llx", ((u64 *)&msg)[cnt]);
+	} else {
+		ffa_err("Sending direct request error (%d)", ret);
+	}
+
+	return ret;
+}
+
+/**
+ *do_ffa_dev_list - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the devices belonging to the UCLASS_FFA
+ * class. Currently, one device is expected to show up: the arm_ffa device
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_dev_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev = NULL;
+	int i, ret;
+
+	ffa_info("arm_ffa uclass entries:");
+
+	for (i = 0, ret = uclass_first_device(UCLASS_FFA, &dev);
+	     dev;
+	     ret = uclass_next_device(&dev), i++) {
+		if (ret)
+			break;
+
+		ffa_info("entry %d - instance %08x, ops %08x, plat %08x",
+			 i,
+			 (u32)map_to_sysmem(dev),
+			 (u32)map_to_sysmem(dev->driver->ops),
+			 (u32)map_to_sysmem(dev_get_plat(dev)));
+	}
+
+	return cmd_process_error(cmdtp, ret);
+}
+
+static struct cmd_tbl armffa_commands[] = {
+	U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_get_singular_partition_info, "", ""),
+	U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_msg_send_direct_req, "", ""),
+	U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_dev_list, "", ""),
+};
+
+/**
+ * do_armffa - the armffa command main function
+ * @cmdtp:	Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function identifies which armffa subcommand to run.
+ * Then, it makes sure the arm_ffa device is probed and
+ * ready for use.
+ * Then, it runs the subcommand.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct cmd_tbl *armffa_cmd;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
+
+	argc -= 2;
+	argv += 2;
+
+	if (!armffa_cmd || argc > armffa_cmd->maxargs)
+		return CMD_RET_USAGE;
+
+	ret = ffa_bus_discover();
+	if (ret != 0)
+		return cmd_process_error(cmdtp, ret);
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
+
+	return cmd_process_error(armffa_cmd, ret);
+}
+
+U_BOOT_CMD(armffa, 4, 1, do_armffa,
+	   "Arm FF-A operations test command",
+	   "getpart <partition UUID>\n"
+	   "	 - lists the partition(s) info\n"
+	   "ping <partition ID>\n"
+	   "	 - sends a data pattern to the specified partition\n"
+	   "devlist\n"
+	   "	 - displays the arm_ffa device info\n");
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index f1427535f9..624e834b1f 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -4,6 +4,7 @@ config ARM_FFA_TRANSPORT
 	bool "Enable Arm Firmware Framework for Armv8-A driver"
 	depends on DM && ARM64
 	select ARM_SMCCC
+	select CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v6 06/10] arm_ffa: introduce the FF-A Sandbox driver
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                       ` (4 preceding siblings ...)
  2022-10-13 10:38                                     ` [PATCH v6 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2022-10-13 10:38                                     ` Abdellatif El Khlifi
  2022-10-13 10:38                                     ` [PATCH v6 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                       ` (5 subsequent siblings)
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-13 10:38 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong, Drew.Reed

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>
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>

---

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 +
 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               |  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 +-
 13 files changed, 939 insertions(+), 14 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 663e2abccd..598ae76e16 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 b20b181ab1..cd5575ce61 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 df6a28ef24..27eb2f7ab3 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 624e834b1f..343f6499d0 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/README.ffa.drv
 
+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 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 324367d12b..2810e4a636 100644
--- a/drivers/firmware/arm-ffa/core.c
+++ b/drivers/firmware/arm-ffa/core.c
@@ -1096,6 +1096,7 @@ static int ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data
 	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
@@ -1109,6 +1110,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
@@ -1122,7 +1124,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");
@@ -1299,15 +1306,16 @@ 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 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:
@@ -1318,9 +1326,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 d146e7b328..6fa097d4ed 100644
--- a/include/arm_ffa.h
+++ b/include/arm_ffa.h
@@ -86,7 +86,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(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 2054b33568..bea7ad7608 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())
 			debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n");
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v6 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                       ` (5 preceding siblings ...)
  2022-10-13 10:38                                     ` [PATCH v6 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
@ 2022-10-13 10:38                                     ` Abdellatif El Khlifi
  2022-10-24 12:10                                       ` Ilias Apalodimas
  2022-10-13 10:38                                     ` [PATCH v6 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                       ` (4 subsequent siblings)
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-13 10:38 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong, Drew.Reed

Add functional test cases for the FF-A core driver

These tests rely on the FF-A Sandbox driver which helps in
 inspecting the FF-A core driver.

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>

---

Changelog:
===============

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

v1: introduce sandbox tests

 MAINTAINERS      |   1 +
 test/dm/Makefile |   2 +
 test/dm/ffa.c    | 394 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 397 insertions(+)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 598ae76e16..bf198f4ce1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -256,6 +256,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/sandbox_arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 5178daa7cf..e5bc4b4bd6 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# (C) Copyright 2022 ARM Limited
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -81,6 +82,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_SANDBOX_FFA) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..052d5fc3f4
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <dm.h>
+#include <dm/test.h>
+#include "../../drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h"
+#include <sandbox_arm_ffa.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Macros */
+
+#define LOG_MSG_SZ (100)
+#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
+
+/* Functional tests for the UCLASS_FFA */
+
+static int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
+{
+	char cmd[LOG_CMD_SZ] = {0};
+
+	console_record_reset();
+
+	snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
+	run_command(cmd, 0);
+
+	ut_assert_console_end();
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_fwk_version(struct ffa_prvdata *prvdata, struct sandbox_ffa_prvdata *sdx_prvdata,
+			     struct unit_test_state *uts)
+{
+	if (prvdata->fwk_version != sdx_prvdata->fwk_version) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: framework version: core = 0x%x , sandbox  = 0x%x", __func__,
+			 prvdata->fwk_version,
+			sdx_prvdata->fwk_version);
+
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_endpoint_id(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (prvdata->id) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: endpoint id: core = 0x%x", __func__, prvdata->id);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_core_dev(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->dev) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: core device NULL", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_sandbox_dev(struct sandbox_ffa_prvdata *sdx_prvdata, struct unit_test_state *uts)
+{
+	if (!sdx_prvdata->dev) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: sandbox device NULL", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_rxtxbuf(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->pair.rxbuf && prvdata->pair.txbuf) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = 0x%llx txbuf = 0x%llx", __func__,
+			 prvdata->pair.rxbuf,
+			 prvdata->pair.txbuf);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_features(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	if (prvdata->pair.rxtx_min_pages != RXTX_4K &&
+	    prvdata->pair.rxtx_min_pages != RXTX_16K &&
+	    prvdata->pair.rxtx_min_pages != RXTX_64K) {
+		snprintf(msg,
+			 LOG_MSG_SZ,
+			 "[%s]: Error: FFA_RXTX_MAP features = 0x%lx",
+			 __func__,
+			 prvdata->pair.rxtx_min_pages);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+	{
+		if (rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	case FFA_RXTX_UNMAP:
+	{
+		if (!rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	default:
+		return CMD_RET_FAILURE;
+	}
+
+	snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__,
+		 (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP"));
+	dm_test_ffa_log(uts, msg);
+
+	return CMD_RET_FAILURE;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	if (rxbuf_owned) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg = {0};
+	u8 cnt;
+
+	ut_assertok(ffa_bus_ops_get()->sync_send_receive(part_id, &msg));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_assertok(((u64 *)&msg)[cnt] != 0xffffffffffffffff);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct sandbox_ffa_prvdata *sdx_prvdata,
+				     struct unit_test_state *uts)
+{
+	u32 count = 0, size = 0;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx, exp_info_idx;
+	int ret;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &count, NULL);
+	/* make sure partitions are detected */
+	ut_assertok(ret != 0);
+	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	ut_assertok(!parts_info);
+
+	size = count * sizeof(struct ffa_partition_info);
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &size, parts_info);
+	if (ret != 0) {
+		free(parts_info);
+		ut_assertok(ret != 0);
+	}
+
+	/*
+	 * SPs found , verify the partitions information
+	 */
+
+	ret = CMD_RET_FAILURE;
+
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		for (exp_info_idx = 0;
+		     exp_info_idx < sdx_prvdata->partitions.count;
+		     exp_info_idx++) {
+			if (parts_info[info_idx].id ==
+			   sdx_prvdata->partitions.descs[exp_info_idx].info.id) {
+				ret = memcmp(&parts_info[info_idx],
+					     &sdx_prvdata->partitions.descs[exp_info_idx]
+					     .info,
+					     sizeof(struct ffa_partition_info));
+				if (ret)
+					free(parts_info);
+				ut_assertok(ret != 0);
+				/* send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
+			}
+			ret = CMD_RET_SUCCESS;
+		}
+	}
+
+	free(parts_info);
+
+	/* Verify  expected partitions found in the emulated secure world*/
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+	struct ffa_sandbox_data func_data = {0};
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	int ret;
+
+	/*  test probing FF-A devices */
+	ut_assertok(ffa_bus_discover());
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+
+	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
+
+	/* make sure private data pointers are retrieved */
+	ut_assertok(prvdata == 0);
+	ut_assertok(sdx_prvdata == 0);
+
+	/* make sure dev devices created */
+	ut_assertok(check_core_dev(prvdata, uts));
+	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
+
+	/* test FFA_VERSION */
+	ut_assertok(check_fwk_version(prvdata, sdx_prvdata, uts));
+
+	/* test FFA_ID_GET */
+	ut_assertok(check_endpoint_id(prvdata, uts));
+
+	/* test FFA_FEATURES */
+	ut_assertok(check_features(prvdata, uts));
+
+	/*  test core RX/TX buffers */
+	ut_assertok(check_rxtxbuf(prvdata, uts));
+
+	/* test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_MAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc1_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc2_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* test FFA_RXTX_UNMAP */
+	ut_assertok(ffa_bus_ops_get()->rxtx_unmap());
+
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_UNMAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+	struct ffa_sandbox_data func_data = {0};
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	u32 count = 0;
+	u16 part_id = 0;
+
+	/*  test probing FF-A devices */
+	ut_assertok(ffa_bus_discover());
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+
+	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
+
+	/* make sure private data pointers are retrieved */
+	ut_assertok(prvdata == 0);
+	ut_assertok(sdx_prvdata == 0);
+
+	/* make sure dev devices created */
+	ut_assertok(check_core_dev(prvdata, uts));
+	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
+
+	/* query partitions count using  invalid arguments  */
+	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, NULL, NULL);
+	ut_assertok(ret != -EINVAL);
+
+	/* query partitions count using an invalid UUID  string */
+	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid_str, &count, NULL);
+	ut_assertok(ret != -EINVAL);
+
+	/* query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, &count, NULL);
+	ut_assertok(count != 0);
+
+	/* query partitions count using a valid UUID  */
+	count = 0;
+	ret = ffa_bus_ops_get()->partition_info_get(valid_svc_uuid, &count, NULL);
+	/* make sure partitions are detected */
+	ut_assertok(ret != 0);
+	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
+
+	/* send data to an invalid partition */
+	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
+	ut_assertok(ret != -EINVAL);
+
+	/* send data to a valid partition */
+	part_id = prvdata->partitions.descs[0].info.id;
+	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
+	ut_assertok(ret != 0);
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v6 08/10] arm_ffa: introduce armffa command Sandbox test
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                       ` (6 preceding siblings ...)
  2022-10-13 10:38                                     ` [PATCH v6 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2022-10-13 10:38                                     ` Abdellatif El Khlifi
  2022-10-13 10:38                                     ` [PATCH v6 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
                                                       ` (3 subsequent siblings)
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-13 10:38 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong, Drew.Reed

Add Sandbox test for the armffa command

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>

---

Changelog:
===============

v4: drop use of helper APIs

v1: introduce armffa command sandbox test

 MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 40 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 43 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index bf198f4ce1..9a90826954 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -256,6 +256,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/sandbox_arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 1bb02d93a2..9a04ea7b9b 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# (C) Copyright 2022 ARM Limited
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -16,3 +17,4 @@ obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
 obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PWM) += pwm.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_SANDBOX_FFA) += armffa.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..531f82066e
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <sandbox_arm_ffa.h>
+#include <string.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define PING_CMD_SIZE 19
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	char ping_cmd[PING_CMD_SIZE] = {0};
+
+	ut_assertok(ffa_bus_discover());
+
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	snprintf(ping_cmd, PING_CMD_SIZE, "armffa ping 0x%x", SANDBOX_SP1_ID);
+
+	/* armffa ping <ID> */
+	ut_assertok(run_command(ping_cmd, 0));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v6 09/10] arm_ffa: efi: introduce FF-A MM communication
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                       ` (7 preceding siblings ...)
  2022-10-13 10:38                                     ` [PATCH v6 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2022-10-13 10:38                                     ` Abdellatif El Khlifi
  2022-10-24 12:30                                       ` Ilias Apalodimas
  2022-10-13 10:38                                     ` [PATCH v6 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
                                                       ` (2 subsequent siblings)
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-13 10:38 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong, Drew.Reed,
	Gowtham Suresh Kumar

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>

---

Changelog:
===============

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

 include/mm_communication.h        |   5 +
 lib/efi_loader/Kconfig            |  14 +-
 lib/efi_loader/efi_variable_tee.c | 264 +++++++++++++++++++++++++++++-
 3 files changed, 277 insertions(+), 6 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..d409bed777 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,8 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +15,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 41756ea539..f0d843d5ca 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -60,13 +60,23 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	depends on OPTEE && ARM_FFA_TRANSPORT
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..04e990880d 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,6 +4,8 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright (C) 2022 ARM Limited
+ *  Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -15,6 +17,36 @@
 #include <malloc.h>
 #include <mm_communication.h>
 
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+#include <arm_ffa.h>
+#include <cpu_func.h>
+#include <mapmem.h>
+
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+#warning "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_SIZE 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_OFFSET
+#warning "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_OFFSET 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+#warning "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_ADDR 0
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+
+const char *mm_sp_svc_uuid = MM_SP_UUID;
+
+static u16 mm_sp_id;
+
+#endif
+
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -24,6 +56,7 @@ struct mm_connection {
 	u32 session;
 };
 
+#if (IS_ENABLED(CONFIG_OPTEE))
 /**
  * get_connection() - Retrieve OP-TEE session for a specific UUID.
  *
@@ -143,13 +176,224 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 
 	return ret;
 }
+#endif
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+/**
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notifies the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret = -1;
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
+
+	ret = ffa_bus_ops_get()->sync_send_receive(mm_sp_id, &msg);
+	if (ret != 0)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	if (sp_event_ret == MM_SUCCESS)
+		return 0;
+
+	/*
+	 * Failure to notify the MM SP
+	 */
+
+	return -EACCES;
+}
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0, size = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &count, NULL);
+	if (ret != 0) {
+		log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
+		return ret;
+	}
+
+	if (!count) {
+		log_info("EFI: No MM partition found\n");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	size = count * sizeof(struct ffa_partition_info);
+
+	/*
+	 * ask the driver to fill the
+	 * buffer with the SPs info
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &size, parts_info);
+	if (ret != 0) {
+		log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * MM SPs found , use the first one
+	 */
+
+	mm_sp_id = parts_info[0].id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
+		log_err("EFI: Failure to discover MM partition ID at boot time\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+	#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+	#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+	if (ffa_ret)
+		unmap_sysmem(virt_shared_buf);
+
+	switch (ffa_ret) {
+	case 0:
+	{
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			unmap_sysmem(virt_shared_buf);
+			return EFI_OUT_OF_RESOURCES;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		unmap_sysmem(virt_shared_buf);
+
+		return EFI_SUCCESS;
+	}
+	case -EINVAL:
+		return EFI_DEVICE_ERROR;
+	case -EPERM:
+		return EFI_INVALID_PARAMETER;
+	case -EACCES:
+		return EFI_ACCESS_DENIED;
+	case -EBUSY:
+		return EFI_OUT_OF_RESOURCES;
+	default:
+		return EFI_ACCESS_DENIED;
+	}
+}
+#endif
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
@@ -162,7 +406,12 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+	ret = ffa_bus_discover();
+	if (ret != 0)
+		ret = optee_mm_communicate(comm_buf, dsize);
+	else
+		ret = ffa_mm_communicate(comm_buf, dsize);
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -258,6 +507,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
 		goto out;
 	}
 	*size = var_payload->size;
+
+	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
+			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
+				MM_VARIABLE_COMMUNICATE_SIZE;
+	#endif
+
 	/*
 	 * There seems to be a bug in EDK2 miscalculating the boundaries and
 	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
@@ -697,7 +953,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v6 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                       ` (8 preceding siblings ...)
  2022-10-13 10:38                                     ` [PATCH v6 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2022-10-13 10:38                                     ` Abdellatif El Khlifi
  2022-10-24 12:13                                       ` Ilias Apalodimas
  2022-10-13 12:07                                     ` [PATCH v6 00/10] introduce Arm FF-A support Ilias Apalodimas
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-13 10:38 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, trini,
	u-boot, vishnu.banavath, xueliang.zhong, Drew.Reed

turn on EFI MM communication

On corstone1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

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>

---

Changelog:
===============

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

 configs/corstone1000_defconfig | 4 ++++
 include/configs/corstone1000.h | 9 +++++++++
 2 files changed, 13 insertions(+)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index ed2e0fe70a..4c9ed9fb71 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -52,3 +52,7 @@ CONFIG_DM_SERIAL=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760=y
 CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
index 8e0230c135..997d0bebaf 100644
--- a/include/configs/corstone1000.h
+++ b/include/configs/corstone1000.h
@@ -14,6 +14,15 @@
 
 #include <linux/sizes.h>
 
+#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
+
+/*
+ * shared buffer physical address used for communication between
+ * u-boot and the MM SP
+ */
+#define FFA_SHARED_MM_BUFFER_ADDR	(0x023F8000)
+#define FFA_SHARED_MM_BUFFER_OFFSET	(0)
+
 #define V2M_BASE		0x80000000
 
 #define CONFIG_PL011_CLOCK	50000000
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 00/10] introduce Arm FF-A support
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                       ` (9 preceding siblings ...)
  2022-10-13 10:38                                     ` [PATCH v6 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
@ 2022-10-13 12:07                                     ` Ilias Apalodimas
  2022-10-14 10:44                                       ` Abdellatif El Khlifi
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
  11 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2022-10-13 12:07 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, jens.wiklander, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong, Drew.Reed

Hi Abdellatif,

On Thu, Oct 13, 2022 at 11:38:47AM +0100, Abdellatif El Khlifi wrote:
> Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [6].
> 
> FF-A describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World. These interfaces enable a pair of
> software sandboxes to communicate with each other. A sandbox aka partition could
> be a VM in the Normal or Secure world, an application in S-EL0, or a
> Trusted OS in S-EL1.
> 
> The FF-A transport is implemented as a data bus and a core driver is provided.
> 
> The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> 
> - Discover the presence of secure partitions (SPs) of interest
> - Access an SP's service through communication protocols
>   e.g. EFI MM communication protocol
> 
> The FF-A support provides the following features:
> 
> - Being generic by design and can be used by any Arm 64-bit platform
> - The FF-A core driver
> - The FF-A bus is discoverable on demand at runtime
> - The driver provides callbacks to be used by clients to access the FF-A bus
> - FF-A driver can be compiled and used without EFI
> - Support for SMCCCv1.2 x0-x17 registers
> - A new command called armffa is provided as an example of how to access the
>   FF-A bus
> - An FF-A Sandbox driver is provided with test cases
> - Support for FF-A MM communication
> - Enabling FF-A and MM communication in Corstone1000 platform
> 
> For more details about the FF-A core driver please refer to [7].
> 
> Please find at [8] an example of the expected boot logs when enabling
> FF-A support for a platform. In this example the platform is
> Corstone1000. But it can be any Arm 64-bit platform.
> 
> Changelog of the major changes:
> ===========================
> 
> v6:
> 
> * remove clearing x0-x17 registers after SMC calls
> * drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)

Thanks! This makes the whole process way way easier.  I am bit overloaded
atm but I'll try squeezing in reviewing these patches

> * drop discovery from initcalls (discovery will be on demand by FF-A users)
> * add FF-A runtime discovery at MM communication level
> * update the documentation and move it to doc/arch/arm64.ffa.rst
> 
> v5: [5]
> 
> * move changelogs in each commit to the changes section
> 
> v4: [4]
> 
> * add FF-A support README (doc/README.ffa.drv)
> * improving error handling by mapping the FF-A errors to standard errors
>   and logs
> * replacing panics with an error log
> * align sandbox driver and tests with the new FF-A driver interfaces
>  and new way of error handling
 
[...]

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v5 02/10] arm64: smccc: clear the Xn registers after SMC calls
  2022-09-30  9:48                                     ` Jens Wiklander
@ 2022-10-14 10:17                                       ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-14 10:17 UTC (permalink / raw)
  To: Jens Wiklander; +Cc: u-boot, nd

On Fri, Sep 30, 2022 at 11:48:04AM +0200, Jens Wiklander wrote:
> On Mon, Sep 26, 2022 at 03:08:19PM +0100, Abdellatif El Khlifi wrote:
> > set to zero the x0-x17 registers
> > 
> > As per the SMCCC v1.2 spec, unused result and scratch registers
> > can leak information after an SMC call. We can mitigate against
> > this risk by returning zero in each register.
> > 
> > The leakage we are referring to is data leakage across exception
> > levels. The intent is to prevent lower exception levels (EL1/EL0)
> > from reading the SMC data exchanged at EL2.
> > 
> > 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>
> > ---
> > 
> > Changelog:
> > ===============
> > 
> > v4:
> > 
> > * move the clearing code into a new macro: clear_gp_regs
> > 
> > v3:
> > 
> > * clear the Xn registers after SMC calls
> > 
> > 
> >  arch/arm/cpu/armv8/smccc-call.S | 9 +++++++++
> >  1 file changed, 9 insertions(+)
> > 
> > diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
> > index ec6f299bc9..32f3eb8eeb 100644
> > --- a/arch/arm/cpu/armv8/smccc-call.S
> > +++ b/arch/arm/cpu/armv8/smccc-call.S
> > @@ -50,6 +50,12 @@ ENDPROC(__arm_smccc_hvc)
> >  
> >  #ifdef CONFIG_ARM64
> >  
> > +	.macro	clear_gp_regs
> > +	.irp	n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17
> > +	mov	x\n, xzr
> > +	.endr
> > +	.endm
> > +
> >  	.macro SMCCC_1_2 instr
> >  	/* Save `res` and free a GPR that won't be clobbered */
> >  	stp     x1, x19, [sp, #-16]!
> > @@ -84,6 +90,9 @@ ENDPROC(__arm_smccc_hvc)
> >  	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
> >  	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
> >  
> > +	/* x0-x17 registers can leak information after an SMC or HVC call. Let's clear them */
> > +	clear_gp_regs
> > +
> 
> This should in my opinion not be needed. The higher exception level should
> only return what it indends to return and certainly not rely on lower
> exception levels to try to hide eventual unintentionally revealed
> secrets.
> 
> In an earlier conversation you said:
> > The leakage we are referring to is data leakage across exception levels.
> > The intent is to prevent lower exception levels (EL1/EL0) to read the
> > data exchanged at EL2.
> > 
> > The linux kernel clears the general purpose registers before switching
> > to EL0. As far as I know u-boot doesn't.
> > 
> > So, the code above makes sure the registers are cleared.
> 
> U-Boot is as far as I know not changing to EL0. Do you have a real example
> where this cleaning actually would be needed? If it's needed I'd expect
> the cleaning to be done just before changing exception level.

No real example for that. But I tried to follow the spec as much as possible.
Since, no real need for this I'm happy to remove the commit and this has
been done in patchset v6. Thanks.

> 
> Cheers,
> Jens
> 
> >  	/* Restore original x19 */
> >  	ldp     xzr, x19, [sp], #16
> >  	ret
> > -- 
> > 2.17.1
> > 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v5 04/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-10-03  8:49                                     ` Jens Wiklander
  2022-10-03 15:22                                       ` Tom Rini
@ 2022-10-14 10:28                                       ` Abdellatif El Khlifi
  1 sibling, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-14 10:28 UTC (permalink / raw)
  To: Jens Wiklander; +Cc: u-boot, nd

On Mon, Oct 03, 2022 at 10:49:23AM +0200, Jens Wiklander wrote:
> On Mon, Sep 26, 2022 at 03:08:21PM +0100, Abdellatif El Khlifi wrote:
> > Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
> > 
> > The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> > describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World leveraging TrustZone
> > technology.
> > 
> > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > querying the FF-A framework from the secure world.
> > 
> > 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> > and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> > 
> > In u-boot FF-A design, FF-A is considered as a discoverable bus.
> > The Secure World is considered as one entity to communicate with
> > using the FF-A bus. FF-A communication is handled by one device and
> > one instance (the bus). This FF-A driver takes care of all the
> > interactions between Normal world and Secure World.
> > 
> > The driver exports its operations to be used by upper layers.
> > 
> > Exported operations:
> > 
> > - partition_info_get
> > - sync_send_receive
> > - rxtx_unmap
> > 
> > This implementation provides an optional feature to copy the driver data
> > to EFI runtime area.
> > 
> > [1]: https://developer.arm.com/documentation/den0077/latest/
> > 
> > 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>
> > ---
> > 
> > Changelog:
> > ===============
> > 
> > v4:
> > 
> > * add doc/README.ffa.drv
> > * moving the FF-A driver work to drivers/firmware/arm-ffa
> > * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
> >   #if defined by #if CONFIG_IS_ENABLED
> > * improving error handling by mapping the FF-A errors to standard errors
> >   and logs
> > * replacing panics with an error log and returning an error code
> > * improving features discovery in FFA_FEATURES by introducing
> >   rxtx_min_pages private data field
> > * add ffa_remove and ffa_bind functions
> > * improve how the driver behaves when bus discovery is done more than
> >   once
> > 
> > v3:
> > 
> > * align the interfaces of the u-boot FF-A driver with those in the linux
> >   FF-A driver
> > * remove the FF-A helper layer
> > * make the u-boot FF-A driver independent from EFI
> > * provide an optional config that enables copying the driver data to EFI
> >   runtime section at ExitBootServices service
> > * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
> > 
> > v2:
> > 
> > * make FF-A bus discoverable using device_{bind, probe} APIs
> > * remove device tree support
> > 
> > v1:
> > 
> > * introduce FF-A bus driver with device tree support
> > 
> >  MAINTAINERS                                   |    7 +
> >  common/board_r.c                              |    9 +
> >  doc/README.ffa.drv                            |  160 ++
> >  drivers/Kconfig                               |    2 +
> >  drivers/Makefile                              |    1 +
> >  drivers/firmware/arm-ffa/Kconfig              |   39 +
> >  drivers/firmware/arm-ffa/Makefile             |    7 +
> >  drivers/firmware/arm-ffa/arm-ffa-uclass.c     |   16 +
> >  drivers/firmware/arm-ffa/arm_ffa_prv.h        |  196 +++
> >  drivers/firmware/arm-ffa/core.c               | 1344 +++++++++++++++++
> >  .../arm-ffa/efi_ffa_runtime_data_mgr.c        |   94 ++
> >  include/arm_ffa.h                             |  127 ++
> >  include/dm/uclass-id.h                        |    4 +
> >  lib/efi_loader/efi_boottime.c                 |   15 +
> >  14 files changed, 2021 insertions(+)
> >  create mode 100644 doc/README.ffa.drv
> >  create mode 100644 drivers/firmware/arm-ffa/Kconfig
> >  create mode 100644 drivers/firmware/arm-ffa/Makefile
> >  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
> >  create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
> >  create mode 100644 drivers/firmware/arm-ffa/core.c
> >  create mode 100644 drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
> >  create mode 100644 include/arm_ffa.h
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 83346183ee..02b84d5074 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -248,6 +248,13 @@ F:	drivers/net/cortina_ni.h
> >  F:	drivers/net/phy/ca_phy.c
> >  F:	configs/cortina_presidio-asic-pnand_defconfig
> >  
> > +ARM FF-A
> > +M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > +S:	Maintained
> > +F:	doc/README.ffa.drv
> > +F:	drivers/firmware/arm-ffa/
> > +F:	include/arm_ffa.h
> > +
> >  ARM FREESCALE IMX
> >  M:	Stefano Babic <sbabic@denx.de>
> >  M:	Fabio Estevam <festevam@gmail.com>
> > diff --git a/common/board_r.c b/common/board_r.c
> > index 56eb60fa27..8c99faddfd 100644
> > --- a/common/board_r.c
> > +++ b/common/board_r.c
> > @@ -7,6 +7,8 @@
> >   * (C) Copyright 2002
> >   * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
> >   * Marius Groeger <mgroeger@sysgo.de>
> > + *
> > + * (C) Copyright 2022 ARM Limited
> >   */
> >  
> >  #include <common.h>
> > @@ -66,6 +68,10 @@
> >  #include <efi_loader.h>
> >  #include <relocate.h>
> >  
> > +#ifdef CONFIG_ARM_FFA_TRANSPORT
> > +#include <arm_ffa.h>
> > +#endif
> > +
> >  DECLARE_GLOBAL_DATA_PTR;
> >  
> >  ulong monitor_flash_len;
> > @@ -770,6 +776,9 @@ static init_fnc_t init_sequence_r[] = {
> >  	INIT_FUNC_WATCHDOG_RESET
> >  	initr_net,
> >  #endif
> > +#ifdef CONFIG_ARM_FFA_TRANSPORT
> > +	ffa_bus_discover,
> > +#endif
> >  #ifdef CONFIG_POST
> >  	initr_post,
> >  #endif
> > diff --git a/doc/README.ffa.drv b/doc/README.ffa.drv
> > new file mode 100644
> > index 0000000000..1c0a33deb8
> > --- /dev/null
> > +++ b/doc/README.ffa.drv
> > @@ -0,0 +1,160 @@
> > +Arm FF-A Driver
> > +====================
> > +
> > +Introduction
> > +--------------------
> > +
> > +FF-A stands for Firmware Framework for Arm A-profile processors.
> > +
> > +FF-A specifies interfaces that enable a pair of software sandboxes to communicate with each other. A sandbox aka partition could
> > +be a VM in the Normal or Secure world, an application in S-EL0, or a Trusted OS in S-EL1.
> 
> These lines are a bit long, from the coding guide lines:
> The preferred limit on the length of a single line is 80 columns.
> 
> > +
> > +This FF-A driver implements the interfaces to communicate with partitions in the Secure world aka Secure partitions (SPs).
> > +
> > +The driver specifically focuses on communicating with SPs that isolate portions of EFI runtime services that must run in a
> > +protected environment which is inaccessible by the Host OS or Hypervisor. Examples of such services are set/get variables.
> > +
> > +FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> > +
> > +- Discover the presence of SPs of interest.
> > +- Access an SP's service through communication protocols e.g. EFI MM communication protocol.
> > +
> > +FF-A and SMC specifications
> > +-------------------------------------------
> > +
> > +The current implementation of the driver relies on FF-A specification v1.0 and uses SMC32 calling convention.
> > +
> > +The driver has been tested with Optee OS which supports SMC32 for most of the SMC ABIs.
> > +
> > +For more details please refer to: https://developer.arm.com/documentation/den0077/a/?lang=en
> > +
> > +The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
> > +
> > +For more details please refer to: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
> > +
> > +Supported hardware
> > +--------------------------------
> > +
> > +Aarch64 plaforms
> > +
> > +Configuration
> > +----------------------
> > +
> > +CONFIG_ARM_FFA_TRANSPORT
> > +    Enables the FF-A bus driver. Turn this on if you want to use FF-A communication.
> > +
> > +CONFIG_ARM_FFA_EFI_RUNTIME_MODE
> > +    Optional config that enables EFI runtime support for FF-A data and code.
> > +    ffa_copy_runtime_data allows to copy the FF-A driver data structures to EFI runtime data section.
> > +    Turning the config on makes ffa_copy_runtime_data available for use and the driver code placed at EFI runtime code section.
> > +    Call ffa_copy_runtime_data at the event on which you want the FF-A data to be copied (example: at ExitBootServices).
> > +
> > +CONFIG_SANDBOX_FFA
> > +    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under Sandbox and provides
> > +    functional tests for FF-A.
> > +
> > +FF-A ABIs under the hood
> > +---------------------------------------
> > +
> > +Invoking an FF-A ABI involves providing to the secure world/hypervisor the expected arguments from the ABI.
> > +
> > +The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction is executed.
> > +
> > +At the secure side level or hypervisor the ABI is handled at a higher exception level and the arguments are read and processed.
> > +
> > +The response is put back through x0 to x7 registers and control is giving back to the u-boot FF-A driver (non secure world).
> 
> U-Boot, non-secure
> 
> > +
> > +The driver reads the response and processes it accordingly.
> > +
> > +This methodology applies to all the FF-A ABIs in the driver.
> > +
> > +FF-A bus discovery in u-boot
> 
> U-Boot, you might as well search and replace.
> 
> > +-------------------------------------------
> > +
> > +When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is automatically discovered at initcall level (after u-boot relocation).
> > +
> > +The function that triggers the discovery process is ffa_bus_discover.
> > +
> > +ffa_bus_discover creates, binds and probes the arm_ffa device using device_{bind, probe} APIs.
> > +
> > +When the device is probed, ffa_probe is called which tries to communicate with the secure world or hypervisor.
> > +
> > +The FF-A bus is usable when these checks succeed:
> > +
> > +- querying the FF-A framework version
> > +- querying from secure world the u-boot endpoint ID
> > +- querying from secure world the supported features of the specified FF-A calls
> > +- mapping the RX/TX buffers
> > +- querying from secure world all the partitions information
> > +
> > +Probing fails when any of these operations fail. The FF-A bus discovery succeeds when probing is successful.
> > +
> > +When discovery fails the arm_ffa device is destroyed.
> > +
> > +The bus driver layer
> > +------------------------------
> > +
> > +The driver comes on top of the SMCCC layer and is implemented in drivers/firmware/arm-ffa/core.c
> > +
> > +The driver provides the following features:
> > +
> > +- Support for the 32-bit version of the following ABIs:
> > +
> > +FFA_VERSION
> > +FFA_ID_GET
> > +FFA_FEATURES
> > +FFA_PARTITION_INFO_GET
> > +FFA_RXTX_UNMAP
> > +FFA_RX_RELEASE
> > +FFA_RUN
> > +FFA_ERROR
> > +FFA_SUCCESS
> > +FFA_INTERRUPT
> > +
> > +- Support for the 64-bit version of the following ABIs:
> > +
> > +FFA_RXTX_MAP
> > +FFA_MSG_SEND_DIRECT_REQ
> > +FFA_MSG_SEND_DIRECT_RESP
> > +
> > +- Processing the received data from the secure world/hypervisor and caching it
> > +
> > +- Hiding from upper layers the FF-A protocol and registers details. Upper layers focus on exchanged data,
> > +the driver takes care of how to transport that to the secure world/hypervisor using FF-A.
> > +
> > +- The driver provides callbacks to be used by clients to access the FF-A bus:
> > +
> > +partition_info_get
> > +sync_send_receive
> > +rxtx_unmap
> > +
> > +- FF-A bus discovery at initcalls level (after u-boot relocation). The bus is up and running if the FF-A framework is responsive and compatible with the driver.
> > +
> > +- When EFI is enabled, unmap the RX/TX buffers at ExitBootServices() level.
> > +
> > +- When CONFIG_ARM_FFA_EFI_RUNTIME_MODE enabled, ffa_copy_runtime_data function is available for use.
> > +
> > +Using armffa command
> > +-----------------------------------
> > +
> > +armffa is a command showcasing how to use the FF-A driver and how to invoke its operations.
> > +
> > +This provides a guidance to the client developers on how to call the FF-A bus interfaces.
> > +
> > +Usage:
> > +
> > +armffa <sub-command> <arguments>
> > +
> > +sub-commands:
> > +
> > +        getpart <partition UUID>
> > +
> > +            lists the partition(s) info
> > +
> > +        ping <partition ID>
> > +
> > +            sends a data pattern to the specified partition
> > +
> > +        devlist
> > +
> > +            displays the arm_ffa device info
> > diff --git a/drivers/Kconfig b/drivers/Kconfig
> > index 8b6fead351..b06b1ae481 100644
> > --- a/drivers/Kconfig
> > +++ b/drivers/Kconfig
> > @@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
> >  
> >  source "drivers/adc/Kconfig"
> >  
> > +source "drivers/firmware/arm-ffa/Kconfig"
> > +
> >  source "drivers/ata/Kconfig"
> >  
> >  source "drivers/axi/Kconfig"
> > diff --git a/drivers/Makefile b/drivers/Makefile
> > index eba9940231..c3bfad94ac 100644
> > --- a/drivers/Makefile
> > +++ b/drivers/Makefile
> > @@ -110,6 +110,7 @@ obj-y += iommu/
> >  obj-y += smem/
> >  obj-y += thermal/
> >  obj-$(CONFIG_TEE) += tee/
> > +obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
> >  obj-y += axi/
> >  obj-y += ufs/
> >  obj-$(CONFIG_W1) += w1/
> > diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> > new file mode 100644
> > index 0000000000..aceb61cf49
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/Kconfig
> > @@ -0,0 +1,39 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +config ARM_FFA_TRANSPORT
> > +	bool "Enable Arm Firmware Framework for Armv8-A driver"
> > +	depends on DM && ARM64
> > +	select ARM_SMCCC
> > +	select LIB_UUID
> > +	select DEVRES
> > +	help
> > +	  The Firmware Framework for Arm A-profile processors (FF-A)
> > +	  describes interfaces (ABIs) that standardize communication
> > +	  between the Secure World and Normal World leveraging TrustZone
> > +	  technology.
> > +
> > +	  This driver is based on FF-A specification v1.0 and uses SMC32
> > +	  calling convention.
> > +
> > +	  FF-A specification:
> > +
> > +	  https://developer.arm.com/documentation/den0077/a/?lang=en
> > +
> > +	  In u-boot FF-A design, FF-A is considered as a discoverable bus.
> > +	  The Secure World is considered as one entity to communicate with
> > +	  using the FF-A bus.
> > +	  FF-A communication is handled by one device and one instance (the bus).
> > +	  This FF-A driver takes care of all the interactions between Normal world
> > +	  and Secure World.
> > +
> > +	  For more details about the FF-A driver, please refer to doc/README.ffa.drv
> > +
> > +config ARM_FFA_EFI_RUNTIME_MODE
> > +	bool "Enable EFI runtime support for FF-A data and code"
> > +	depends on ARM_FFA_TRANSPORT && EFI_LOADER
> > +	help
> > +	  Allows FF-A driver data structures and code to be accessible at EFI runtime.
> > +	  FF-A data is copied by ffa_copy_runtime_data function.
> > +	  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.
> > diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
> > new file mode 100644
> > index 0000000000..0b9b0a61b4
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/Makefile
> > @@ -0,0 +1,7 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +#
> > +# (C) Copyright 2022 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > +#
> > +
> > +obj-y += arm-ffa-uclass.o core.o
> > +obj-$(CONFIG_ARM_FFA_EFI_RUNTIME_MODE) += efi_ffa_runtime_data_mgr.o
> > diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> > new file mode 100644
> > index 0000000000..7d9695d289
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> > @@ -0,0 +1,16 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <asm/global_data.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +UCLASS_DRIVER(ffa) = {
> > +	.name		= "ffa",
> > +	.id		= UCLASS_FFA,
> > +};
> > diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> > new file mode 100644
> > index 0000000000..7bc90f7f66
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> > @@ -0,0 +1,196 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_PRV_H
> > +#define __ARM_FFA_PRV_H
> > +
> > +#include <arm_ffa.h>
> > +#include <linux/bitfield.h>
> > +#include <linux/bitops.h>
> > +#include <linux/arm-smccc.h>
> > +
> > +/*
> > + * This header is private. It is exclusively used by the FF-A driver
> > + */
> > +
> > +/* FF-A core driver name */
> > +#define FFA_DRV_NAME "arm_ffa"
> > +
> > +/* FF-A driver version definitions */
> > +
> > +#define MAJOR_VERSION_MASK		GENMASK(30, 16)
> > +#define MINOR_VERSION_MASK		GENMASK(15, 0)
> > +#define GET_FFA_MAJOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> > +#define GET_FFA_MINOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> > +#define PACK_VERSION_INFO(major, minor)			\
> > +	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
> > +	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> > +
> > +#define FFA_MAJOR_VERSION		(1)
> > +#define FFA_MINOR_VERSION		(0)
> > +#define FFA_VERSION_1_0		\
> > +			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> > +
> > +/* Endpoint ID mask (u-boot endpoint ID) */
> > +
> > +#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define GET_SELF_ENDPOINT_ID(x)		\
> > +			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> > +
> > +#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
> > +#define PREP_SELF_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> > +
> > +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> > +
> > +#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define PREP_PART_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> > +
> > +/*
> > + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> > + */
> > +
> > +#define FFA_SMC(calling_convention, func_num)				\
> > +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
> > +			   ARM_SMCCC_OWNER_STANDARD, (func_num))
> > +
> > +#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> > +#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
> > +
> > +enum ffa_abis {
> > +	FFA_ERROR					= 0x60,
> > +	FFA_SUCCESS					= 0x61,
> > +	FFA_INTERRUPT				= 0x62,
> > +	FFA_VERSION					= 0x63,
> > +	FFA_FEATURES				= 0x64,
> > +	FFA_RX_RELEASE				= 0x65,
> > +	FFA_RXTX_MAP				= 0x66,
> > +	FFA_RXTX_UNMAP			= 0x67,
> > +	FFA_PARTITION_INFO_GET		= 0x68,
> > +	FFA_ID_GET					= 0x69,
> > +	FFA_RUN						= 0x6D,
> > +	FFA_MSG_SEND_DIRECT_REQ	= 0x6F,
> > +	FFA_MSG_SEND_DIRECT_RESP	= 0x70,
> > +
> > +	/* to be updated when adding new FFA IDs */
> > +	FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
> > +	FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
> > +};
> > +
> > +/* number of the errors supported by the FF-A specification */
> > +#define MAX_NUMBER_FFA_ERR 9
> > +
> > +/* container structure and helper macros to map between an FF-A error and relevant error log */
> > +struct ffa_abi_errmap {
> > +	char *err_str[MAX_NUMBER_FFA_ERR];
> > +};
> > +
> > +#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
> > + *
> > + */
> > +struct ffa_partition_uuid {
> > +	u32 a1; /* w1 */
> > +	u32 a2; /* w2 */
> > +	u32 a3; /* w3 */
> > +	u32 a4; /* w4 */
> > +};
> > +
> > +/**
> > + * enum ffa_rxtx_buf_sizes - minimum sizes supported
> > + * for the RX/TX buffers
> > + */
> > +enum ffa_rxtx_buf_sizes {
> > +	RXTX_4K,
> > +	RXTX_64K,
> > +	RXTX_16K
> > +};
> > +
> > +/**
> > + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> > + * @rxbuf:	virtual address of the RX buffer
> > + * @txbuf:	virtual address of the TX buffer
> > + * @rxtx_min_pages:	RX/TX buffers minimum size in pages
> > + *
> > + * Data structure hosting the virtual addresses of the mapped RX/TX buffers
> > + * These addresses are used by the FF-A functions that use the RX/TX buffers
> > + */
> > +struct ffa_rxtxpair {
> > +	u64 rxbuf; /* virtual address */
> > +	u64 txbuf; /* virtual address */
> > +	size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
> > +};
> > +
> > +/**
> > + * struct ffa_partition_desc - the secure partition descriptor
> > + * @info:	partition information
> > + * @sp_uuid:	the secure partition UUID
> > + *
> > + * Each partition has its descriptor containing the partitions information and the UUID
> > + */
> > +struct ffa_partition_desc {
> > +	struct ffa_partition_info info;
> > +	struct ffa_partition_uuid sp_uuid;
> > +};
> > +
> > +/**
> > + * struct ffa_partitions - descriptors for all secure partitions
> > + * @count:	The number of partitions descriptors
> > + * @descs	The partitions descriptors table
> > + *
> > + * This data structure contains the partitions descriptors table
> > + */
> > +struct ffa_partitions {
> > +	u32 count;
> > +	struct ffa_partition_desc *descs; /* virtual address */
> > +};
> > +
> > +/**
> > + * struct ffa_prvdata - the driver private data structure
> > + *
> > + * @dev:	The arm_ffa device under u-boot driver model
> > + * @ffa_ops:	The driver operations structure
> > + * @fwk_version:	FF-A framework version
> > + * @id:	u-boot endpoint ID
> > + * @partitions:	The partitions descriptors structure
> > + * @pair:	The RX/TX buffers pair
> > + * @invoke_ffa_fn:	The function executing the FF-A function
> > + *
> > + * The driver data structure hosting all resident data.
> > + */
> > +struct ffa_prvdata {
> > +	struct udevice *dev;
> > +	struct ffa_bus_ops ffa_ops;
> > +	u32 fwk_version;
> > +	u16 id;
> > +	struct ffa_partitions partitions;
> > +	struct ffa_rxtxpair pair;
> > +	invoke_ffa_fn_t invoke_ffa_fn;
> > +};
> > +
> > +/**
> > + * ffa_device_get - create, bind and probe the arm_ffa device
> > + */
> > +int ffa_device_get(void);
> > +
> > +/**
> > + * ffa_bus_prvdata_get - bus driver private data getter
> > + */
> > +struct ffa_prvdata **ffa_bus_prvdata_get(void);
> > +
> > +#endif
> > diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
> > new file mode 100644
> > index 0000000000..41c7b96e68
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/core.c
> > @@ -0,0 +1,1344 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include "arm_ffa_prv.h"
> > +#include <asm/global_data.h>
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <dm/device-internal.h>
> > +#include <dm/devres.h>
> > +#include <dm/root.h>
> > +#include <linux/errno.h>
> > +#include <linux/sizes.h>
> > +#include <log.h>
> > +#include <malloc.h>
> > +#include <string.h>
> > +#include <uuid.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/**
> > + * The device private data structure containing all the resident
> > + * data read from secure world
> > + */
> > +__ffa_runtime_data struct ffa_prvdata *ffa_priv_data;
> > +
> > +/* Error mapping declarations */
> > +
> > +__ffa_runtime_data int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
> > +	0,
> > +	-EOPNOTSUPP,	/* NOT_SUPPORTED */
> > +	-EINVAL,	/* INVALID_PARAMETERS */
> > +	-ENOMEM,	/* NO_MEMORY */
> > +	-EBUSY,		/* BUSY */
> > +	-EINTR,		/* INTERRUPTED */
> > +	-EACCES,	/* DENIED */
> > +	-EAGAIN,	/* RETRY */
> > +	-ECANCELED,	/* ABORTED */
> > +};
> > +
> > +struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
> > +		{
> > +			"",
> > +			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
> > +			"", /* INVALID_PARAMETERS */
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"", /* DENIED */
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
> > +		{
> > +			"",
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +			"", /* INVALID_PARAMETERS */
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"", /* DENIED */
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
> > +		{
> > +			"",
> > +			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
> > +			"", /* INVALID_PARAMETERS */
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"", /* DENIED */
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
> > +		{
> > +			"",
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +			"INVALID_PARAMETERS: Unrecognized UUID",
> > +			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
> > +			"BUSY: RX buffer of the caller is not free",
> > +			"", /* INTERRUPTED */
> > +			"DENIED: Callee is not in a state to handle this request",
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
> > +			{
> > +			"",
> > +			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
> > +			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"", /* DENIED */
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
> > +			{
> > +			"",
> > +			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
> > +			"", /* INVALID_PARAMETERS */
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"DENIED: Caller did not have ownership of the RX buffer",
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
> > +			{
> > +			"",
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
> > +			"NO_MEMORY: Not enough memory",
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"DENIED: Buffer pair already registered",
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +};
> > +
> > +/**
> > + * ffa_to_std_errno - convert FF-A error code to standard error code
> > + * @ffa_errno:	Error code returned by the FF-A ABI
> > + *
> > + * This runtime function maps the given FF-A error code as specified
> > + * by the spec to a u-boot standard error code.
> > + *
> > + * Return:
> > + *
> > + * The standard error code on success. . Otherwise, failure
> > + */
> > +__ffa_runtime int ffa_to_std_errno(int ffa_errno)
> > +{
> > +	int err_idx = -ffa_errno;
> > +
> > +	/* map the FF-A error code to the standard u-boot error code */
> > +	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
> > +		return ffa_to_std_errmap[err_idx];
> > +	return -EINVAL;
> > +}
> > +
> > +/**
> > + * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
> > + * @ffa_id:	FF-A ABI ID
> > + * @ffa_errno:	Error code returned by the FF-A ABI
> > + *
> > + * This boot time function maps the FF-A error code to the error log relevant to the
> > + * selected FF-A ABI. Then the error log is printed.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. . Otherwise, failure
> > + */
> > +int ffa_print_error_log(u32 ffa_id, int ffa_errno)
> > +{
> > +	int err_idx = -ffa_errno, abi_idx = 0;
> > +
> > +	/* map the FF-A error code to the corresponding error log */
> > +
> > +	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
> > +		return -EINVAL;
> > +
> > +	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
> > +		return -EINVAL;
> > +
> > +	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
> > +	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
> > +		return -EINVAL;
> > +
> > +	if (!err_msg_map[abi_idx].err_str || !err_msg_map[abi_idx].err_str[err_idx])
> > +		return -EINVAL;
> > +
> > +	ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Driver core functions
> > + */
> > +
> > +/**
> > + * ffa_remove_device - removes the arm_ffa device
> > + * @dev:	the device to be removed
> > + *
> > + * This boot time function makes sure the arm_ffa device is removed
> > + * No need to free the kmalloced data when the device is destroyed.
> > + * It's automatically done by devm management by
> > + * device_remove() -> device_free() -> devres_release_probe().
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_remove_device(struct udevice *dev)
> > +{
> > +	int ret;
> > +
> > +	if (!dev) {
> > +		ffa_err("no udevice found");
> > +		return -ENODEV;
> > +	}
> > +
> > +	ret = device_remove(dev, DM_REMOVE_NORMAL);
> > +	if (ret) {
> > +		ffa_err("unable to remove. err:%d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	ffa_info("device removed and freed");
> > +
> > +	ret = device_unbind(dev);
> > +	if (ret) {
> > +		ffa_err("unable to unbind. err:%d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	ffa_info("device unbound");
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_device_get - create, bind and probe the arm_ffa device
> > + *
> > + * This boot time function makes sure the arm_ffa device is
> > + * created, bound to this driver, probed and ready to use.
> > + * Arm FF-A transport is implemented through a single u-boot
> > + * device managing the FF-A bus (arm_ffa).
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_device_get(void)
> > +{
> > +	int ret;
> > +	struct udevice *dev = NULL;
> > +
> > +	ret = device_bind(dm_root(),
> > +			  DM_DRIVER_GET(arm_ffa),
> > +			  FFA_DRV_NAME,
> > +			  NULL,
> > +			  ofnode_null(),
> > +			  &dev);
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* The FF-A bus discovery succeeds when probing is successful */
> > +	ret = device_probe(dev);
> > +	if (ret) {
> > +		ffa_err("arm_ffa device probing failed");
> > +		ffa_remove_device(dev);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_get_version - FFA_VERSION handler function
> > + *
> > + * This is the boot time function that implements FFA_VERSION FF-A function
> > + * to get from the secure world the FF-A framework version
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_version(void)
> > +{
> > +	u16 major, minor;
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_VERSION),
> > +			.a1 = FFA_VERSION_1_0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> 
> Why not support the latest version, 1.1?

We only need the v1.0 features.

> 
> The zero initializations are done implicitly so you could just as well remove
> them.

Regarding all the code comments made in this patch, they have been  addressed in patchset v6. Thanks.

> 
> > +			}, &res);
> > +
> > +	ffa_errno = (int)res.a0;
> 
> Is this cast needed, or any of the other casts below in this function?
> 
> > +	if (ffa_errno < 0) {
> > +		ffa_print_error_log(FFA_VERSION, ffa_errno);
> > +		return ffa_to_std_errno(ffa_errno);
> > +	}
> > +
> > +	major = GET_FFA_MAJOR_VERSION((u32)res.a0);
> > +	minor = GET_FFA_MINOR_VERSION((u32)res.a0);
> > +
> > +	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> > +		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
> > +		ffa_info("Versions are compatible ");
> > +
> > +		ffa_priv_data->fwk_version = (u32)res.a0;
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
> > +		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +	return -EPROTONOSUPPORT;
> > +}
> > +
> > +/**
> > + * ffa_get_endpoint_id - FFA_ID_GET handler function
> > + *
> > + * This is the boot time function that implements FFA_ID_GET FF-A function
> > + * to get from the secure world u-boot endpoint ID
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_endpoint_id(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_ID_GET),
> > +			.a1 = 0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
> > +		ffa_info("endpoint ID is %u", ffa_priv_data->id);
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = (int)res.a2;
> > +
> > +	ffa_print_error_log(FFA_ID_GET, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
> > + * @prop_field: properties field obtained from FFA_FEATURES ABI
> > + *
> > + * This boot time function sets the minimum number of pages
> > + *  in each of the RX/TX buffers in the private data structure
> > + *
> > + * Return:
> > + *
> > + * buf_4k_pages points to the returned number of pages
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
> > +{
> > +	if (!ffa_priv_data)
> > +		return -EINVAL;
> > +
> > +	switch (prop_field) {
> > +	case RXTX_4K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 1;
> > +		break;
> > +	case RXTX_16K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 4;
> > +		break;
> > +	case RXTX_64K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 16;
> > +		break;
> > +	default:
> > +		ffa_err("RX/TX buffer size not supported");
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
> > + *
> > + * This is the boot time function that implements FFA_FEATURES FF-A function
> > + * to retrieve the FFA_RXTX_MAP features
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_rxtx_map_features(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_FEATURES),
> > +			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
> > +			.a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> > +		return ffa_set_rxtx_buffers_pages_cnt((u32)res.a2);
> > +
> > +	ffa_errno = (int)res.a2;
> > +	ffa_print_error_log(FFA_FEATURES, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> > + *
> > + * This is the boot time function used to free the RX/TX buffers
> > + *
> > + */
> > +static void ffa_free_rxtx_buffers(void)
> > +{
> > +	ffa_info("Freeing RX/TX buffers");
> > +
> > +	if (ffa_priv_data->pair.rxbuf) {
> > +		free((void *)ffa_priv_data->pair.rxbuf);
> > +		ffa_priv_data->pair.rxbuf = 0;
> > +	}
> > +
> > +	if (ffa_priv_data->pair.txbuf) {
> > +		free((void *)ffa_priv_data->pair.txbuf);
> > +		ffa_priv_data->pair.txbuf = 0;
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
> > + *
> > + * This is the boot time function used by ffa_map_rxtx_buffers to allocate
> > + * the RX/TX buffers before mapping them. The allocated memory is physically
> > + * contiguous since memalign ends up calling malloc which allocates
> > + * contiguous memory in u-boot.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_alloc_rxtx_buffers(void)
> > +{
> > +	u64 bytes;
> > +
> > +	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
> > +		 ffa_priv_data->pair.rxtx_min_pages);
> > +
> > +	bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> > +
> > +	/* RX/TX buffers addresses should be PAGE_SIZE aligned */
> > +
> > +	ffa_priv_data->pair.rxbuf = (u64)memalign(PAGE_SIZE, bytes);
> 
> Shouldn't this be "bytes" aligned too? Same below with the TX buffer.
> 
> > +	if (!ffa_priv_data->pair.rxbuf) {
> > +		ffa_err("failure to allocate RX buffer");
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
> > +
> > +	ffa_priv_data->pair.txbuf = (u64)memalign(PAGE_SIZE, bytes);
> > +	if (!ffa_priv_data->pair.txbuf) {
> > +		free((void *)ffa_priv_data->pair.rxbuf);
> > +		ffa_priv_data->pair.rxbuf = 0;
> > +		ffa_err("failure to allocate the TX buffer");
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
> > +
> > +	/*
> > +	 * make sure the buffers are cleared before use
> > +	 */
> > +	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
> > +	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> > + *
> > + * This is the boot time function that implements FFA_RXTX_MAP FF-A function
> > + * to map the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_map_rxtx_buffers(void)
> > +{
> > +	int ret;
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ret = ffa_alloc_rxtx_buffers();
> > +	if (ret)
> > +		return ret;
> > +
> > +	/*
> > +	 * we need to pass the physical addresses of the RX/TX buffers
> > +	 * in u-boot physical/virtual mapping is 1:1
> > +	 *no need to convert from virtual to physical
> > +	 */
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
> > +			.a1 = ffa_priv_data->pair.txbuf,
> > +			.a2 = ffa_priv_data->pair.rxbuf,
> > +			.a3 = ffa_priv_data->pair.rxtx_min_pages,
> > +			.a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_info("RX/TX buffers mapped");
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = (int)res.a2;
> > +	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
> > +
> > +	ffa_free_rxtx_buffers();
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
> > + *
> > + * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function
> > + * to unmap the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_unmap_rxtx_buffers(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
> > +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id),
> > +			.a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_free_rxtx_buffers();
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = (int)res.a2;
> > +	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
> > + *
> > + * This is the boot time function that invokes FFA_RX_RELEASE FF-A function
> > + * to release the ownership of the RX buffer
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_release_rx_buffer(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
> > +			.a1 = 0, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> > +		return 0;
> > +
> > +	ffa_errno = (int)res.a2;
> > +	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_uuid_are_identical - checks whether two given UUIDs are identical
> > + * @uuid1: first UUID
> > + * @uuid2: second UUID
> > + *
> > + * This is a boot time function used by ffa_read_partitions_info to search
> > + * for a UUID in the partitions descriptors table
> > + *
> > + * Return:
> > + *
> > + * 1 when UUIDs match. Otherwise, 0
> > + */
> > +int ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
> > +			   const struct ffa_partition_uuid *uuid2)
> > +{
> > +	if (!uuid1 || !uuid2)
> > +		return 0;
> > +
> > +	return (!memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid)));
> 
> Please drop the outer ().
> 
> > +}
> > +
> > +/**
> > + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> > + *							and saves it in the private structure
> > + * @count: The number of partitions queried
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + *
> > + * This is the boot time function that reads the partitions information
> > + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> > + * data structure.
> > + *
> > + * Return:
> > + *
> > + * The private data structure is updated with the partition(s) information
> > + * 0 is returned on success. Otherwise, failure
> > + */
> > +static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
> > +{
> > +	if (!count) {
> > +		ffa_err("no partition detected");
> > +		return -ENODATA;
> > +	}
> > +
> > +	ffa_info("Reading partitions data from the RX buffer");
> > +
> > +	if (!part_uuid) {
> > +		/*
> > +		 * querying information of all partitions
> > +		 */
> > +		u64 buf_bytes;
> > +		u64 data_bytes;
> > +		u32 desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +
> > +		data_bytes = count * sizeof(struct ffa_partition_desc);
> > +
> > +		buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> > +
> > +		if (data_bytes > buf_bytes) {
> > +			ffa_err("partitions data size exceeds the RX buffer size:");
> > +			ffa_err("    sizes in bytes: data %llu , RX buffer %llu ",
> > +				data_bytes,
> > +				buf_bytes);
> > +
> > +			return -ENOMEM;
> > +		}
> > +
> > +		ffa_priv_data->partitions.descs = (struct ffa_partition_desc *)
> > +			devm_kmalloc(ffa_priv_data->dev, data_bytes, __GFP_ZERO);
> 
> There's no need to cast the void pointer.
> 
> > +		if (!ffa_priv_data->partitions.descs) {
> > +			ffa_err("cannot  allocate partitions data buffer");
> > +			return -ENOMEM;
> > +		}
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> > +
> > +		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
> > +			ffa_priv_data->partitions.descs[desc_idx].info =
> > +				parts_info[desc_idx];
> > +
> > +			ffa_info("Partition ID %x : info cached",
> > +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> > +		}
> > +
> > +		ffa_priv_data->partitions.count = count;
> > +
> > +		ffa_info("%d partition(s) found and cached", count);
> > +
> > +	} else {
> > +		u32 rx_desc_idx, cached_desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +		u8 desc_found;
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> > +
> > +		/*
> > +		 * search for the SP IDs read from the RX buffer
> > +		 * in the already cached SPs.
> > +		 * Update the UUID when ID found.
> > +		 */
> > +		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
> > +			desc_found = 0;
> > +
> > +			/*
> > +			 * search the current ID in the cached partitions
> > +			 */
> > +			for (cached_desc_idx = 0;
> > +			     cached_desc_idx < ffa_priv_data->partitions.count;
> > +			     cached_desc_idx++) {
> > +				/*
> > +				 * save the UUID
> > +				 */
> > +				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
> > +				    parts_info[rx_desc_idx].id) {
> > +					ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
> > +						*part_uuid;
> > +
> > +					desc_found = 1;
> > +					break;
> > +				}
> > +			}
> > +
> > +			if (!desc_found)
> > +				return -ENODATA;
> > +		}
> > +	}
> > +
> > +	return  0;
> > +}
> > +
> > +/**
> > + * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
> > + *
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + * @pcount: Pointer to the number of partitions variable filled when querying
> > + *
> > + * This is the boot time function that executes the FFA_PARTITION_INFO_GET
> > + * to query the partitions data. Then, it calls ffa_read_partitions_info
> > + * to save the data in the private data structure.
> > + *
> > + * After reading the data the RX buffer is released using ffa_release_rx_buffer
> > + *
> > + * Return:
> > + *
> > + * When part_uuid is NULL, all partitions data are retrieved from secure world
> > + * When part_uuid is non NULL, data for partitions matching the given UUID are
> > + * retrieved and the number of partitions is returned
> > + * 0 is returned on success. Otherwise, failure
> > + */
> > +static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
> > +				     u32 *pcount)
> > +{
> > +	struct ffa_partition_uuid query_uuid = {0};
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	/*
> > +	 * If a UUID is specified. Information for one or more
> > +	 * partitions in the system is queried. Otherwise, information
> > +	 * for all installed partitions is queried
> > +	 */
> > +
> > +	if (part_uuid) {
> > +		if (!pcount)
> > +			return -EINVAL;
> > +
> > +		query_uuid = *part_uuid;
> > +	} else if (pcount) {
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
> > +			.a1 = query_uuid.a1,
> > +			.a2 = query_uuid.a2,
> > +			.a3 = query_uuid.a3,
> > +			.a4 = query_uuid.a4,
> > +			.a5 = 0,
> > +			.a6 = 0,
> > +			.a7 = 0,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		int ret;
> > +
> > +		/*
> > +		 * res.a2 contains the count of partition information descriptors
> > +		 * populated in the RX buffer
> > +		 */
> > +		if (res.a2) {
> > +			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
> > +			if (ret) {
> > +				ffa_err("failed to read partition(s) data , error (%d)", ret);
> > +				ffa_release_rx_buffer();
> > +				return -EINVAL;
> > +			}
> > +		}
> > +
> > +		/*
> > +		 * return the SP count (when querying using a UUID)
> > +		 */
> > +		if (pcount)
> > +			*pcount = (u32)res.a2;
> > +
> > +		/*
> > +		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
> > +		 * is assigned to the consumer (u-boot). So, we need to give
> > +		 * the ownership back to the SPM or hypervisor
> > +		 */
> > +		ret = ffa_release_rx_buffer();
> > +
> > +		return ret;
> > +	}
> > +
> > +	ffa_errno = (int)res.a2;
> > +	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
> > + *
> > + * The passed arguments:
> > + * Mode 1: When getting from the driver the number of
> > + *	secure partitions:
> > + *	@uuid_str: pointer to the UUID string
> > + *	@parts_size: pointer to the variable that contains the number of partitions
> > + *			 The variable will be set by the driver
> > + *	@buffer: NULL
> > + *
> > + * Mode 2: When requesting the driver to return the
> > + *	partitions information:
> > + *	@uuid_str: pointer to the UUID string
> > + *	@parts_size: pointer to the size of the SPs information buffer in bytes
> > + *	@buffer: pointer to SPs information buffer
> > + *		(allocated by the client).
> > + *		The buffer will be filled by the driver
> > + *
> > + * This is the boot time function that queries the secure partition data from
> > + * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
> > + * FF-A function to query the partition information from secure world.
> > + *
> > + * A client of the FF-A driver should know the UUID of the service it wants to
> > + * access. It should use the UUID to request the FF-A driver to provide the
> > + * partition(s) information of the service. The FF-A driver uses
> > + * PARTITION_INFO_GET to obtain this information. This is implemented through
> > + * ffa_get_partitions_info function.
> > + * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
> > + * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
> > + * They are not saved (already done). We only update the UUID in the cached area.
> > + * This assumes that partitions data does not change in the secure world.
> > + * Otherwise u-boot will have an outdated partition data. The benefit of caching
> > + * the information in the FF-A driver is to accommodate discovery after
> > + * ExitBootServices().
> > + *
> > + * When invoked through a client request, ffa_get_partitions_info should be
> > + * called twice. First call is to get from the driver the number of secure
> > + * partitions (SPs) associated to a particular UUID.
> > + * Then, the caller (client) allocates the buffer to host the SPs data and
> > + * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
> > + * buffer.
> > + *
> > + * To achieve the mechanism described above, ffa_get_partitions_info uses the
> > + * following functions:
> > + *		ffa_read_partitions_info
> > + *		ffa_query_partitions_info
> > + *
> > + * Return:
> > + *
> > + * @parts_size: When pointing to the number of partitions variable, the number is
> > + * set by the driver.
> > + * When pointing to the partitions information buffer size, the buffer will be
> > + * filled by the driver.
> > + *
> > + * On success 0 is returned. Otherwise, failure
> > + */
> > +static int ffa_get_partitions_info(const char *uuid_str,
> > +				   u32 *parts_size, struct ffa_partition_info *buffer)
> > +{
> > +	/*
> > +	 * fill_data:
> > +	 * 0: return the SP count
> > +	 * 1: fill SP data and return it to the caller
> > +	 * -1: undefined mode
> > +	 */
> > +	int fill_data = -1;
> > +	u32 desc_idx, client_desc_idx;
> > +	struct ffa_partition_uuid part_uuid = {0};
> > +	u32 client_desc_max_cnt;
> > +	u32 parts_found = 0;
> > +
> > +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
> > +		ffa_err("no partition installed");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!uuid_str) {
> > +		ffa_err("no UUID provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!parts_size) {
> > +		ffa_err("no size/count provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (be_uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
> > +		ffa_err("invalid UUID");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!buffer) {
> > +		/* Mode 1: getting the number of secure partitions */
> > +
> > +		fill_data = 0;
> > +
> > +		ffa_info("Preparing for checking partitions count");
> > +
> > +	} else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
> > +		   !(*parts_size % sizeof(struct ffa_partition_info))) {
> > +		/* Mode 2: retrieving the partitions information */
> > +
> > +		fill_data = 1;
> > +
> > +		client_desc_idx = 0;
> > +
> > +		/*
> > +		 * number of empty descriptors preallocated by the caller
> > +		 */
> > +		client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
> > +
> > +		ffa_info("Preparing for filling partitions info");
> > +
> > +	} else {
> > +		ffa_err("invalid function arguments provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_info("Searching partitions using the provided UUID");
> > +
> > +	/*
> > +	 * search in the cached partitions
> > +	 */
> > +	for (desc_idx = 0;
> > +	     desc_idx < ffa_priv_data->partitions.count;
> > +	     desc_idx++) {
> > +		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
> > +					   &part_uuid)) {
> > +			ffa_info("Partition ID %x matches the provided UUID",
> > +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> > +
> > +			parts_found++;
> > +
> > +			if (fill_data) {
> > +				/*
> > +				 * trying to fill the partition info in the input buffer
> > +				 */
> > +
> > +				if (client_desc_idx < client_desc_max_cnt) {
> > +					buffer[client_desc_idx++] =
> > +						ffa_priv_data->partitions.descs[desc_idx].info;
> > +					continue;
> > +				}
> > +
> > +				ffa_err("failed to fill the current descriptor client buffer full");
> > +				return -ENOBUFS;
> > +			}
> > +		}
> > +	}
> > +
> > +	if (!parts_found) {
> > +		int ret;
> > +
> > +		ffa_info("No partition found. Querying framework ...");
> > +
> > +		ret = ffa_query_partitions_info(&part_uuid, &parts_found);
> > +
> > +		if (ret == 0) {
> > +			if (!fill_data) {
> > +				*parts_size = parts_found;
> > +
> > +				ffa_info("Number of partition(s) found matching the UUID: %d",
> > +					 parts_found);
> > +			} else {
> > +				/*
> > +				 * If SPs data detected, they are already in the private data
> > +				 * structure, retry searching SP data again to return them
> > +				 *  to the caller
> > +				 */
> > +				if (parts_found)
> > +					ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
> > +				else
> > +					ret = -ENODATA;
> > +			}
> > +		}
> > +
> > +		return ret;
> > +	}
> > +
> > +	/* partition(s) found */
> > +	if (!fill_data)
> > +		*parts_size = parts_found;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_cache_partitions_info - Queries and saves all secure partitions data
> > + *
> > + * This is a boot time function that invokes FFA_PARTITION_INFO_GET FF-A
> > + * function to query from secure world all partitions information.
> > + *
> > + * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
> > + * All installed partitions information are returned. We cache them in the
> > + * resident private data structure and we keep the UUID field empty
> > + * (in FF-A 1.0 UUID is not provided by the partition descriptor)
> > + *
> > + * This function is called at the device probing level.
> > + * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_cache_partitions_info(void)
> > +{
> > +	return ffa_query_partitions_info(NULL, NULL);
> > +}
> > +
> > +/**
> > + * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> > + * @dst_part_id: destination partition ID
> > + * @msg: pointer to the message data preallocated by the client (in/out)
> > + *
> > + * This is the runtime function that implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * FF-A functions.
> > + *
> > + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> > + * The response from the secure partition is handled by reading the
> > + * FFA_MSG_SEND_DIRECT_RESP arguments.
> > + *
> > + * The maximum size of the data that can be exchanged is 40 bytes which is
> > + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> > + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int __ffa_runtime ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
> > +		return -EINVAL;
> > +
> > +	/* No partition installed */
> > +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
> > +		return -ENODEV;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ),
> > +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
> > +				PREP_PART_ENDPOINT_ID(dst_part_id),
> > +			.a2 = 0,
> > +			.a3 = msg->data0,
> > +			.a4 = msg->data1,
> > +			.a5 = msg->data2,
> > +			.a6 = msg->data3,
> > +			.a7 = msg->data4,
> > +			}, &res);
> > +
> > +	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
> > +		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RUN),
> > +			.a1 = res.a1, .a2 = 0, .a3 = 0, .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> 
> How can the caller tell this response apart from a FFA_MSG_SEND_DIRECT_RESP?

According to the FF-A 1.0 spec, paragraph 10.2:

Successful completion of FFA_MSG_SEND_DIRECT_REQ is indicated through an
invocation of the following interfaces by the callee:
FFA_MSG_SEND_DIRECT_RESP, FFA_INTERRUPT, FFA_SUCCESS, FFA_ERROR.

All these are supported by the u-boot FF-A driver.

> 
> > +		/* Message sent with no response */
> > +		return 0;
> > +	}
> > +
> > +	if (res.a0 == FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP)) {
> > +		/*
> > +		 * Message sent with response
> > +		 * extract the return data
> > +		 */
> > +		msg->data0 = res.a3;
> > +		msg->data1 = res.a4;
> > +		msg->data2 = res.a5;
> > +		msg->data3 = res.a6;
> > +		msg->data4 = res.a7;
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = (int)res.a2;
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * __arm_ffa_fn_smc - 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 low level SMC assembly function
> > + *
> > + * Return: void
> > + */
> > +void __ffa_runtime __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
> > +{
> > +	arm_smccc_1_2_smc(&args, res);
> > +}
> > +
> > +/**
> > + * ffa_set_smc_conduit - Set the SMC conduit
> > + *
> > + * This boot time function selects the SMC conduit by setting the driver invoke function
> > + * to SMC assembly function
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_set_smc_conduit(void)
> > +{
> > +	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
> > +
> > +	if (!ffa_priv_data->invoke_ffa_fn) {
> > +		ffa_err("failure to set the invoke function");
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_info("Conduit is SMC");
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_set_bus_ops - Set the bus driver operations
> > + *
> > + * Setting the driver callbacks.
> > + *
> > + */
> > +static void ffa_set_bus_ops(void)
> > +{
> > +	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
> > +	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
> > +	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
> > +}
> > +
> > +/**
> > + * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
> > + * @dev:	the arm_ffa device
> > + *
> > + * This boot time function creates the main data structure embedding all the driver data.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_alloc_prvdata(struct udevice *dev)
> > +{
> > +	if (!dev) {
> > +		ffa_err("no udevice found");
> > +		return -ENODEV;
> > +	}
> > +
> > +	/* The device is registered with the DM. Let's create the driver main data structure*/
> > +
> > +	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
> > +	if (!ffa_priv_data) {
> > +		ffa_err("can not allocate the driver main data structure");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	ffa_priv_data->dev = dev;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_probe - The driver probe function
> > + * @dev:	the arm_ffa device
> > + *
> > + * Probing is done at boot time and triggered by the uclass device discovery.
> > + * At probe level the following actions are done:
> > + *	- setting the conduit
> > + *	- querying the FF-A framework version
> > + *	- querying from secure world the u-boot endpoint ID
> > + *	- querying from secure world the supported features of FFA_RXTX_MAP
> > + *	- mapping the RX/TX buffers
> > + *	- querying from secure world all the partitions information
> > + *
> > + * All data queried from secure world is saved in the resident private data structure.
> > + *
> > + * The probe will fail if either FF-A framework is not detected or the
> > + * FF-A requests are not behaving correctly. This ensures that the
> > + * driver is not installed and its operations are not exported to the clients.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_probe(struct udevice *dev)
> > +{
> > +	int ret;
> > +
> > +	ret = ffa_alloc_prvdata(dev);
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ffa_set_bus_ops();
> > +
> > +	ret = ffa_set_smc_conduit();
> 
> What if there's a hypervisor involved and HVC would be expected intead?

At this stage of development, we only support a Hypervisor that can trap an SMC if the need arises.

> 
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_version();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_endpoint_id();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_rxtx_map_features();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_map_rxtx_buffers();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_cache_partitions_info();
> 
> Why are we saving all the found partitions in a cache? It seems that
> FFA_PARTITION_INFO_GET could be called each time when needed instead
> without any noticeable overhead. Or is the result cached for some other
> reason?

The RX/TX buffers are only available at EFI boot time. Querying partitions is done
at EFI boot time and data is cached for future use including EFI runtime use. RX/TX buffers
are unmapped before EFI runtime mode starts. If we would allow RX/TX buffers created
by u-boot to be available at EFI runtime, secure world will get confused about
RX/TX buffers ownership (owned by the kernel ? By u-boot ? ).

> 
> > +	if (ret != 0) {
> > +		ffa_free_rxtx_buffers();
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_remove - The driver remove function
> > + * @dev:	the arm_ffa device
> > + * When the device is about to be removed ,  unmap the RX/TX buffers and free the memory
> > + * Return:
> > + *
> > + * 0 on success.
> > + */
> > +static int ffa_remove(struct udevice *dev)
> > +{
> > +	ffa_info("removing the device");
> > +
> > +	ffa_unmap_rxtx_buffers();
> > +
> > +	if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
> > +		ffa_free_rxtx_buffers();
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_unbind - The driver unbind function
> > + * @dev:	the arm_ffa device
> > + * After the device is removed and memory freed the device is unbound
> > + * Return:
> > + *
> > + * 0 on success.
> > + */
> > +static int ffa_unbind(struct udevice *dev)
> > +{
> > +	ffa_info("unbinding the device , private data already released");
> > +
> > +	ffa_priv_data = NULL;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_bus_ops_get - bus driver operations getter
> > + *
> > + * Return:
> > + * This runtime function returns a pointer to the driver operations structure
> > + */
> > +const struct ffa_bus_ops * __ffa_runtime ffa_bus_ops_get(void)
> > +{
> > +	return &ffa_priv_data->ffa_ops;
> > +}
> > +
> > +/**
> > + * ffa_bus_prvdata_get - bus driver private data getter
> > + *
> > + * Return:
> > + * This boot time function returns a pointer to the main private data structure
> > + */
> > +struct ffa_prvdata **ffa_bus_prvdata_get(void)
> > +{
> > +	return &ffa_priv_data;
> > +}
> > +
> > +/**
> > + * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
> > + *
> > + * This boot time function makes sure the FF-A bus is discoverable.
> > + * Then, the arm_ffa device is probed and 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.
> > + * All FF-A clients should use the arm_ffa device to use the FF-A transport.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_bus_discover(void)
> > +{
> > +	int ret = 0;
> > +
> > +	if (!ffa_priv_data)
> > +		ret = ffa_device_get();
> > +
> > +	return ret;
> > +}
> > +
> > +/**
> > + * Declaring the arm_ffa driver under UCLASS_FFA
> > + */
> > +
> > +U_BOOT_DRIVER(arm_ffa) = {
> > +	.name		= FFA_DRV_NAME,
> > +	.id		= UCLASS_FFA,
> > +	.probe		= ffa_probe,
> > +	.remove		= ffa_remove,
> > +	.unbind		= ffa_unbind,
> > +};
> > diff --git a/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c b/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
> > new file mode 100644
> > index 0000000000..c76cf2147b
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/efi_ffa_runtime_data_mgr.c
> > @@ -0,0 +1,94 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include "arm_ffa_prv.h"
> > +
> > +/**
> > + * ffa_copy_runtime_data - copy the private data structure  to the runtime area
> > + *
> > + * This boot time function copies the arm_ffa driver data structures including
> > + *  partitions data to the EFI runtime data section.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +efi_status_t ffa_copy_runtime_data(void)
> > +{
> > +	efi_status_t efi_ret;
> > +	efi_uintn_t prvdata_pages;
> > +	efi_uintn_t descs_pages;
> > +	struct ffa_prvdata **prvdata = NULL; /* Pointer to the current structure */
> > +	struct ffa_prvdata *runtime_prvdata = NULL; /* Pointer to the structure runtime copy */
> > +	u64 runtime_descs = 0;
> > +
> > +	prvdata = ffa_bus_prvdata_get();
> > +
> > +	printf("INFO: EFI: FFA: prv data area at 0x%llx\n", (u64)prvdata);
> > +
> > +	/* allocate private data runtime area */
> > +
> > +	prvdata_pages = efi_size_in_pages(sizeof(struct ffa_prvdata));
> > +	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> > +				     EFI_RUNTIME_SERVICES_DATA,
> > +				     prvdata_pages,
> > +				     (u64 *)&runtime_prvdata);
> 
> Better to use a temporary u64 instead of casting the pointer.
> 
> > +
> > +	if (efi_ret != EFI_SUCCESS) {
> > +		printf("ERROR: EFI: FFA: allocating runtime data (err: 0x%lx, addr 0x%llx)\n",
> > +		       efi_ret, (u64)runtime_prvdata);
> > +
> > +		return efi_ret;
> > +	}
> > +
> > +	printf("INFO: EFI: FFA: runtime data area at 0x%llx\n", (u64)runtime_prvdata);
> > +
> > +	if (!runtime_prvdata)
> > +		return EFI_INVALID_PARAMETER;
> > +
> > +	/* allocate the partition data runtime area */
> > +
> > +	descs_pages = efi_size_in_pages((*prvdata)->partitions.count *
> > +					sizeof(struct ffa_partition_desc));
> > +	efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> > +				     EFI_RUNTIME_SERVICES_DATA,
> > +				     descs_pages,
> > +				     &runtime_descs);
> > +
> > +	if (efi_ret != EFI_SUCCESS) {
> > +		printf("ERROR: EFI: FFA: allocating runtime SPs data (err: 0x%lx, addr 0x%llx)\n",
> > +		       efi_ret, runtime_descs);
> > +
> > +		efi_free_pages((u64)runtime_prvdata, prvdata_pages);
> > +
> > +		return efi_ret;
> > +	}
> > +
> > +	printf("INFO: EFI: FFA: SPs runtime area at 0x%llx\n", (u64)runtime_descs);
> > +
> > +	if (!runtime_descs)
> > +		return EFI_INVALID_PARAMETER;
> > +
> > +	*runtime_prvdata = **prvdata;
> 
> With this you copy fwk_versien. This field will become out of data if
> the kernel driver negotiates a different framework version.

Very valid point thanks. The version can be negotiated as per the spec.
However, v1.1 is backwards compatible with v1.0. So even if the kernel negotiates,
EFI RT FFA_MSG_SEND_DIRECT_REQ calls should work.
The problematic ABIs would be the memory management ABIs and
FFA_PARTITION_INFO_GET (See v1.1 spec paragraph 18.6).
But we do not use any of these ABIs in EFI RT.

So, no need to copy that framework version to the RT structure.

Ilias advised to remove EFI RT support from the patchset and adding it later
when needed. When it's decided to add RT support back again, we will not copy
the framework version to the RT structure.

This has been addressed in patchset v6.

> 
> > +
> > +	runtime_prvdata->dev = NULL;
> > +	runtime_prvdata->ffa_ops.partition_info_get = NULL;
> > +	runtime_prvdata->ffa_ops.rxtx_unmap = NULL;
> > +	runtime_prvdata->partitions.descs = (struct ffa_partition_desc *)runtime_descs;
> > +	runtime_prvdata->pair.rxbuf = 0;
> > +	runtime_prvdata->pair.txbuf = 0;
> > +
> > +	/*
> > +	 * Update the private data structure pointer in the driver
> > +	 * no need to free the old structure. devm takes care of that
> > +	 */
> > +	*prvdata = runtime_prvdata;
> > +
> > +	printf("INFO: EFI: FFA: runtime prv data now at 0x%llx , SPs count %d\n",
> > +	       (u64)*prvdata, (*prvdata)->partitions.count);
> > +
> > +	return 0;
> > +}
> > diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> > new file mode 100644
> > index 0000000000..f17b100497
> > --- /dev/null
> > +++ b/include/arm_ffa.h
> > @@ -0,0 +1,127 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_H
> > +#define __ARM_FFA_H
> > +
> > +#include <linux/printk.h>
> > +
> > +/*
> > + * This header is public. It can be used by clients to access
> > + * data structures and definitions they need
> > + */
> > +
> > +/*
> > + * Macros for displaying logs
> > + */
> > +
> > +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +
> > +/*
> > + * struct ffa_partition_info - Partition information descriptor
> > + * @id:	Partition ID
> > + * @exec_ctxt:	Execution context count
> > + * @properties:	Partition properties
> > + *
> > + * Data structure containing information about partitions instantiated in the system
> > + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> > + */
> > +struct  __packed ffa_partition_info {
> > +	u16 id;
> > +	u16 exec_ctxt;
> > +/* partition supports receipt of direct requests */
> > +#define FFA_PARTITION_DIRECT_RECV	BIT(0)
> > +/* partition can send direct requests. */
> > +#define FFA_PARTITION_DIRECT_SEND	BIT(1)
> > +/* partition can send and receive indirect messages. */
> > +#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
> > +	u32 properties;
> > +};
> > +
> > +/*
> > + * struct ffa_send_direct_data - Data structure hosting the data
> > + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * @data0-4:	Data read/written from/to x3-x7 registers
> > + *
> > + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> > + * or read from FFA_MSG_SEND_DIRECT_RESP
> > + */
> > +
> > +/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
> > +struct __packed ffa_send_direct_data {
> > +	unsigned long data0; /* w3/x3 */
> > +	unsigned long data1; /* w4/x4 */
> > +	unsigned long data2; /* w5/x5 */
> > +	unsigned long data3; /* w6/x6 */
> > +	unsigned long data4; /* w7/x7 */
> > +};
> > +
> > +#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
> > +
> > +#include <efi_loader.h>
> > +
> > +/*
> > + *  __ffa_runtime - controls whether functions are
> > + * available after calling the EFI ExitBootServices service.
> > + * Functions tagged with these keywords are resident (available at boot time and
> > + * at runtime)
> > + */
> > +
> > +#define __ffa_runtime_data __efi_runtime_data
> > +#define __ffa_runtime __efi_runtime
> > +
> > +#else
> > +
> > +/*
> > + *  The FF-A driver is independent from EFI
> > + */
> > +
> > +#define __ffa_runtime_data
> > +#define __ffa_runtime
> > +
> > +#endif
> > +
> > +/**
> > + * struct ffa_bus_ops - The driver operations structure
> > + * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
> > + * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
> > + * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
> > + *
> > + * The data structure providing all the operations supported by the driver.
> > + * This structure is EFI runtime resident.
> > + */
> > +struct ffa_bus_ops {
> > +	int (*partition_info_get)(const char *uuid_str,
> > +				  u32 *parts_size, struct ffa_partition_info *buffer);
> > +	int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg);
> > +	int (*rxtx_unmap)(void);
> > +};
> > +
> > +/**
> > + * The device driver and the Uclass driver public functions
> > + */
> > +
> > +/**
> > + * ffa_bus_ops_get - driver operations getter
> > + */
> > +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
> > + */
> > +int ffa_bus_discover(void);
> > +
> > +#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE)
> > +
> > +/**
> > + * ffa_copy_runtime_data - copy the private data structure and the SPs data to the runtime area
> > + */
> > +efi_status_t ffa_copy_runtime_data(void);
> > +
> > +#endif
> > +
> > +#endif
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index a432e43871..5dd698b7a9 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -4,6 +4,9 @@
> >   *
> >   * (C) Copyright 2012
> >   * Pavel Herrmann <morpheus.ibis@gmail.com>
> > + *
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  
> >  #ifndef _DM_UCLASS_ID_H
> > @@ -55,6 +58,7 @@ enum uclass_id {
> >  	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
> >  	UCLASS_ETH,		/* Ethernet device */
> >  	UCLASS_ETH_PHY,		/* Ethernet PHY device */
> > +	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
> >  	UCLASS_FIRMWARE,	/* Firmware */
> >  	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
> >  	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
> > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> > index 6f7333638a..af0b0f3db1 100644
> > --- a/lib/efi_loader/efi_boottime.c
> > +++ b/lib/efi_loader/efi_boottime.c
> > @@ -3,6 +3,9 @@
> >   * EFI application boot time services
> >   *
> >   * Copyright (c) 2016 Alexander Graf
> > + *
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  
> >  #include <common.h>
> > @@ -23,6 +26,10 @@
> >  #include <asm/setjmp.h>
> >  #include <linux/libfdt_env.h>
> >  
> > +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
> > +#include <arm_ffa.h>
> > +#endif
> > +
> >  DECLARE_GLOBAL_DATA_PTR;
> >  
> >  /* Task priority level */
> > @@ -2178,6 +2185,14 @@ 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)
> > +		/* 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");
> > +		else
> > +			debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
> > +#endif
> > +
> >  	/* Patch out unsupported runtime function */
> >  	efi_runtime_detach();
> >  
> > -- 
> > 2.17.1
> > 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v5 09/10] arm_ffa: introduce FF-A MM communication
  2022-09-29  9:32                                     ` Ilias Apalodimas
@ 2022-10-14 10:38                                       ` Abdellatif El Khlifi
  2022-10-14 15:55                                         ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-14 10:38 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, nd

On Thu, Sep 29, 2022 at 12:32:42PM +0300, Ilias Apalodimas wrote:
> Hi Abdellatif, 
> 
> > --- a/arch/arm/cpu/armv8/cache.S
> > +++ b/arch/arm/cpu/armv8/cache.S
> > @@ -3,6 +3,9 @@
> >   * (C) Copyright 2013
> >   * David Feng <fenghua@phytium.com.cn>
> >   *
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + *
> >   * This file is based on sample code from ARMv8 ARM.
> >   */
> >  
> > @@ -21,7 +24,11 @@
> >   * x1: 0 clean & invalidate, 1 invalidate only
> >   * x2~x9: clobbered
> >   */
> > +#ifdef CONFIG_EFI_LOADER
> > +.pushsection .text.efi_runtime, "ax"
> 
> Maybe we discussed this in the past and I forgot,  but why would you need 
> __asm_dcache_level, __asm_dcache_all, __asm_invalidate_dcache_alla etc in
> the runtime section ?

Because cache invalidation needs to be done at ffa_mm_communicate() level (v4 patchset).
That code is runtime compatible so all the called functions must be under .text.efi_runtime

However, since we agreed to drop EFI runtime support from the patchset, v6 patchset takes
care of that.

> 
> > +#else
> >  .pushsection .text.__asm_dcache_level, "ax"
> > +#endif
> >  ENTRY(__asm_dcache_level)
> >  	lsl	x12, x0, #1
> >  	msr	csselr_el1, x12		/* select cache level */
> > @@ -65,7 +72,11 @@ ENDPROC(__asm_dcache_level)
> >   *
> >   * flush or invalidate all data cache by SET/WAY.
> >   */
> > +#ifdef CONFIG_EFI_LOADER
> > +.pushsection .text.efi_runtime, "ax"
> > +#else
> >  .pushsection .text.__asm_dcache_all, "ax"
> > +#endif
> >  ENTRY(__asm_dcache_all)
> >  	mov	x1, x0
> >  	dsb	sy
> > @@ -109,7 +120,11 @@ ENTRY(__asm_flush_dcache_all)
> >  ENDPROC(__asm_flush_dcache_all)
> >  .popsection
> >  
> > +#ifdef CONFIG_EFI_LOADER
> > +.pushsection .text.efi_runtime, "ax"
> > +#else
> >  .pushsection .text.__asm_invalidate_dcache_all, "ax"
> > +#endif
> >  ENTRY(__asm_invalidate_dcache_all)
> >  	mov	x0, #0x1
> >  	b	__asm_dcache_all
> > @@ -182,7 +197,11 @@ ENTRY(__asm_invalidate_icache_all)
> >  ENDPROC(__asm_invalidate_icache_all)
> >  .popsection
> >  
> > +#ifdef CONFIG_EFI_LOADER
> > +.pushsection .text.efi_runtime, "ax"
> > +#else
> >  .pushsection .text.__asm_invalidate_l3_dcache, "ax"
> > +#endif
> >  WEAK(__asm_invalidate_l3_dcache)
> >  	mov	x0, #0			/* return status as success */
> >  	ret
> > diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
> > index e4736e5643..45f57372c2 100644
> > --- a/arch/arm/cpu/armv8/cache_v8.c
> > +++ b/arch/arm/cpu/armv8/cache_v8.c
> > @@ -5,10 +5,14 @@
> >   *
> >   * (C) Copyright 2016
> >   * Alexander Graf <agraf@suse.de>
> > + *
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  
> >  #include <common.h>
> >  #include <cpu_func.h>
> > +#include <efi_loader.h>
> >  #include <hang.h>
> >  #include <log.h>
> >  #include <asm/cache.h>
> > @@ -445,7 +449,7 @@ __weak void mmu_setup(void)
> >  /*
> >   * Performs a invalidation of the entire data cache at all levels
> >   */
> > -void invalidate_dcache_all(void)
> > +void __efi_runtime invalidate_dcache_all(void)
> >  {
> >  	__asm_invalidate_dcache_all();
> >  	__asm_invalidate_l3_dcache();
> > diff --git a/include/mm_communication.h b/include/mm_communication.h
> > index e65fbde60d..fe9104c56d 100644
> > --- a/include/mm_communication.h
> 
> [...]
> 
> >   * always begin with efi_mm_communicate_header.
> >   */
> > -struct __packed efi_mm_communicate_header {
> > +struct efi_mm_communicate_header {
> >  	efi_guid_t header_guid;
> >  	size_t     message_len;
> >  	u8         data[];
> > @@ -145,7 +150,7 @@ struct smm_variable_communicate_header {
> >   * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
> >   *
> >   */
> > -struct smm_variable_access {
> > +struct __packed smm_variable_access {
> 
> You are randomly adding and deleting __packed cwin both structs. But you can't do that.
> Those structs are defined in StandAloneMM.  This is the reason each struct
> description has the corresponding EDK2 definition. 

Thanks for the comment.

However, we are not setting randomly the __packed keyword. There is a good reason for that.
It has been explained before in this reply [1]. Basically it's because of data padding issues
breaking the communication between u-boot and secure world (Optee).

When upgrading Optee to v3.18, no issues anymore.

The __packed changes have been dropped in patchset v6.

[1]: https://lore.kernel.org/all/20220926105620.GA22382@e121910.cambridge.arm.com/

> 
> >  	efi_guid_t  guid;
> >  	efi_uintn_t data_size;
> >  	efi_uintn_t name_size;
> > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > index b8fb2701a7..d292f57244 100644
> > --- a/lib/efi_loader/Kconfig
> > +++ b/lib/efi_loader/Kconfig
> > @@ -61,13 +61,23 @@ config EFI_VARIABLE_FILE_STORE
> >  	  stored as file /ubootefi.var on the EFI system partition.
> >  
> >  config EFI_MM_COMM_TEE
> > -	bool "UEFI variables storage service via OP-TEE"
> > -	depends on OPTEE
> > +	bool "UEFI variables storage service via the trusted world"
> > +	depends on OPTEE || ARM_FFA_TRANSPORT
> 
> I think we discussed this in the past.  I don't want ifdefs in the code for
> that.  FF-A is a discoverable bus.  So I think what we should do here, is
> fire up the variable access driver -> probe for FF-A -> decide what to use.
> 
> So it looks something like
>     **************************
>     **** Variable Driver *****
>     **************************
>                 |
>                 |
>                 |
>    ***************************
>    ****** Discover FF-A ******
>    ***************************
>         |                 |
> 	| yes             | No
>         |                 |
>       
>       Use SP          Use OP-TEE

In patchset v6, FF-A discovery is done at runtime and on demand. In our case at
the MM Variable Driver as you recommended. Thanks.

> 
> >  	help
> > +	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
> > +	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> > +	  When using the u-boot FF-A  driver any MM SP is supported.
> > +
> >  	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
> >  	  variable related operations to that. The application will verify,
> >  	  authenticate and store the variables on an RPMB.
> >  
> > +	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> > +	  operations to the MM SP running in the secure world.
> > +	  A door bell mechanism is used to notify the SP when there is data in the shared
> > +	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
> > +	  the door bell event.
> > +
> >  config EFI_VARIABLE_NO_STORE
> >  	bool "Don't persist non-volatile UEFI variables"
> >  	help
> > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> > index d404343a7d..8a397ea21b 100644
> > --- a/lib/efi_loader/efi_boottime.c
> > +++ b/lib/efi_loader/efi_boottime.c
> > @@ -2193,6 +2193,13 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
> >  			debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
> >  #endif
> >  
> > +#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE) && !CONFIG_IS_ENABLED(SANDBOX_FFA)
> > +		if (ffa_copy_runtime_data())
> > +			printf("ERROR: EFI: FFA: copying runtime data\n");
> > +		else
> > +			printf("INFO: EFI: FFA: runtime data copied\n");
> > +#endif
> > +
> >  	/* Patch out unsupported runtime function */
> >  	efi_runtime_detach();
> >  
> > diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> > index dfef18435d..d6f24f85bd 100644
> > --- a/lib/efi_loader/efi_variable_tee.c
> > +++ b/lib/efi_loader/efi_variable_tee.c
> > @@ -4,6 +4,8 @@
> >   *
> >   *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
> >   *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
> > + *  Copyright (C) 2022 ARM Limited
> > + *  Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  
> >  #include <common.h>
> > @@ -15,6 +17,36 @@
> >  #include <malloc.h>
> >  #include <mm_communication.h>
> >  
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +
> > +#include <arm_ffa.h>
> > +#include <cpu_func.h>
> > +#include <mapmem.h>
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> > +#warning "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_SIZE 0
> > +#endif
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_OFFSET
> > +#warning "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_OFFSET 0
> > +#endif
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> > +#warning "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_ADDR 0
> > +#endif
> > +
> > +/* MM return codes */
> > +#define MM_SUCCESS (0)
> > +
> > +const char *mm_sp_svc_uuid = MM_SP_UUID;
> > +
> > +static __efi_runtime_data u16 mm_sp_id;
> > +
> > +#endif
> > +
> >  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
> >  static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
> >  static efi_uintn_t max_payload_size;	/* func + data */
> > @@ -24,6 +56,7 @@ struct mm_connection {
> >  	u32 session;
> >  };
> >  
> > +#if (IS_ENABLED(CONFIG_OPTEE))
> >  /**
> >   * get_connection() - Retrieve OP-TEE session for a specific UUID.
> >   *
> > @@ -143,16 +176,227 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
> >  
> >  	return ret;
> >  }
> > +#endif
> > +
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> >  
> >  /**
> > - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
> > + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> > + *
> > + * Notifies the MM partition in the trusted world that
> > + * data is available in the shared buffer.
> > + * This is a blocking call during which trusted world has exclusive access
> > + * to the MM shared buffer.
> > + *
> > + * Return:
> > + *
> > + * 0 on success
> > + */
> > +static int __efi_runtime ffa_notify_mm_sp(void)
> > +{
> > +	struct ffa_send_direct_data msg = {0};
> > +	int ret;
> > +	int sp_event_ret = -1;
> > +
> > +	if (!ffa_bus_ops_get())
> > +		return -EINVAL;
> > +
> > +	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
> > +
> > +	ret = ffa_bus_ops_get()->sync_send_receive(mm_sp_id, &msg);
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	sp_event_ret = msg.data0; /* x3 */
> > +
> > +	if (sp_event_ret == MM_SUCCESS)
> > +		return 0;
> > +
> > +	/*
> > +	 * Failure to notify the MM SP
> > +	 */
> > +
> > +	return -EACCES;
> > +}
> > +
> > +/**
> > + * ffa_discover_mm_sp_id() - Query the MM partition ID
> > + *
> > + * Use the FF-A driver to get the MM partition ID.
> > + * If multiple partitions are found, use the first one.
> > + * This is a boot time function.
> > + *
> > + * Return:
> > + *
> > + * 0 on success
> > + */
> > +static int ffa_discover_mm_sp_id(void)
> > +{
> > +	u32 count = 0, size = 0;
> > +	int ret;
> > +	struct ffa_partition_info *parts_info;
> > +
> > +	if (!ffa_bus_ops_get())
> > +		return -EINVAL;
> > +
> > +	/*
> > +	 * get from the driver the count of the SPs matching the UUID
> > +	 */
> > +	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &count, NULL);
> > +	if (ret != 0) {
> > +		log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	if (!count) {
> > +		log_info("EFI: No MM partition found\n");
> > +		return ret;
> > +	}
> > +
> > +	/*
> > +	 * pre-allocate a buffer to be filled by the driver
> > +	 * with	 ffa_partition_info structs
> > +	 */
> > +
> > +	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
> > +
> > +	parts_info = calloc(count, sizeof(struct ffa_partition_info));
> > +	if (!parts_info)
> > +		return -EINVAL;
> > +
> > +	size = count * sizeof(struct ffa_partition_info);
> > +
> > +	/*
> > +	 * ask the driver to fill the
> > +	 * buffer with the SPs info
> > +	 */
> > +	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &size, parts_info);
> > +	if (ret != 0) {
> > +		log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret);
> > +		free(parts_info);
> > +		return ret;
> > +	}
> > +
> > +	/*
> > +	 * MM SPs found , use the first one
> > +	 */
> > +
> > +	mm_sp_id = parts_info[0].id;
> > +
> > +	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
> > +
> > +	free(parts_info);
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
> > + * @comm_buf:		locally allocated communication buffer used for rx/tx
> > + * @dsize:				communication buffer size
> > + *
> > + * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
> > + * that there is data to read from the shared buffer.
> > + * Communication with the MM SP is performed using FF-A transport.
> > + * On the event, MM SP can read the data from the buffer and
> > + * update the MM shared buffer with response data.
> > + * The response data is copied back to the communication buffer.
> > + *
> > + * Return:
> > + *
> > + * EFI status code
> > + */
> > +static efi_status_t __efi_runtime ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
> > +{
> 
> If you are registering this as a *runtime* service you should also tweak
> the RT_PROPERTIES TABLE and enable runtime services (e.g SetVariable).
> Otherwise having as runtime makes little sense.  To be honest I'd much
> prefer this whole patchset without the runtime parts.  It's much easier to
> review and reason about and we can always add runtime later.

EFI runtime support removed from the FF-A work in patchset v6.

> 
> > +	ulong tx_data_size;
> > +	int ffa_ret;
> > +	struct efi_mm_communicate_header *mm_hdr;
> > +	void *virt_shared_buf;
> > +
> > +	if (!comm_buf)
> > +		return EFI_INVALID_PARAMETER;
> > +
> > +	/* Discover MM partition ID at boot time */
> > +	if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
> > +		log_err("EFI: Failure to discover MM partition ID at boot time\n");
> > +		return EFI_UNSUPPORTED;
> > +	}
> > +
> > +	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> > +	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
> > +
> > +	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
> > +		return EFI_INVALID_PARAMETER;
> > +
> > +	/* Copy the data to the shared buffer */
> > +
> > +	virt_shared_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
> > +	efi_memcpy_runtime(virt_shared_buf, comm_buf, tx_data_size);
> > +
> > +	/*
> > +	 * The secure world might have cache disabled for
> > +	 * the device region used for shared buffer (which is the case for Optee).
> > +	 * In this case, the secure world reads the data from DRAM.
> > +	 * Let's flush the cache so the DRAM is updated with the latest data.
> > +	 */
> > +	#ifdef CONFIG_ARM64
> > +	invalidate_dcache_all();
> > +	#endif
> > +
> > +	/* Announce there is data in the shared buffer */
> > +
> > +	ffa_ret = ffa_notify_mm_sp();
> > +	if (ffa_ret)
> > +		unmap_sysmem(virt_shared_buf);
> > +
> > +	switch (ffa_ret) {
> > +	case 0:
> > +	{
> > +		ulong rx_data_size;
> > +		/* Copy the MM SP response from the shared buffer to the communication buffer */
> > +		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> > +			sizeof(efi_guid_t) +
> > +			sizeof(size_t);
> > +
> > +		if (rx_data_size > comm_buf_size) {
> > +			unmap_sysmem(virt_shared_buf);
> > +			return EFI_OUT_OF_RESOURCES;
> > +		}
> > +
> > +		efi_memcpy_runtime(comm_buf, virt_shared_buf, rx_data_size);
> > +		unmap_sysmem(virt_shared_buf);
> > +
> > +		return EFI_SUCCESS;
> > +	}
> > +	case -EINVAL:
> > +		return EFI_DEVICE_ERROR;
> > +	case -EPERM:
> > +		return EFI_INVALID_PARAMETER;
> > +	case -EACCES:
> > +		return EFI_ACCESS_DENIED;
> > +	case -EBUSY:
> > +		return EFI_OUT_OF_RESOURCES;
> > +	default:
> > +		return EFI_ACCESS_DENIED;
> > +	}
> > +}
> > +#endif
> > +
> > +/**
> > + * mm_communicate() - Adjust the communication buffer to the MM SP and send
> >   * it to OP-TEE
> >   *
> > - * @comm_buf:		locally allocted communcation buffer
> > + * @comm_buf:		locally allocated communication buffer
> >   * @dsize:		buffer size
> > + *
> > + * The MM SP (also called partition) can be StandAlonneMM or smm-gateway.
> > + * The comm_buf format is the same for both partitions.
> > + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> > + * When using the u-boot FF-A  driver, StandAlonneMM and smm-gateway are supported.
> > + *
> >   * Return:		status code
> >   */
> > -static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> > +static efi_status_t __efi_runtime mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> 
> The optee version of the function can't be on the efi_runtime section.  The
> reason is that almost the entire of the OP-TEE subsystem is not marked as
> runtime, which will lead to a crash if we ever take that path.
> 
> >  {
> >  	efi_status_t ret;
> >  	struct efi_mm_communicate_header *mm_hdr;
> > @@ -162,7 +406,11 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> >  	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> >  	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
> >  
> > +	#if (IS_ENABLED(CONFIG_OPTEE))
> >  	ret = optee_mm_communicate(comm_buf, dsize);
> > +	#elif (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +	ret = ffa_mm_communicate(comm_buf, dsize);
> 
> If we enable runtime discovery of optee vs ffa, we can get rid of that and
> just pass an extra argument to mm_communicate
> 
> Thanks
> /Ilias
> > +	#endif
> >  	if (ret != EFI_SUCCESS) {
> >  		log_err("%s failed!\n", __func__);
> >  		return ret;
> > @@ -258,6 +506,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
> >  		goto out;
> >  	}
> >  	*size = var_payload->size;
> > +
> > +	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
> > +			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
> > +				MM_VARIABLE_COMMUNICATE_SIZE;
> > +	#endif
> > +
> >  	/*
> >  	 * There seems to be a bug in EDK2 miscalculating the boundaries and
> >  	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> > @@ -697,7 +952,7 @@ void efi_variables_boot_exit_notify(void)
> >  		ret = EFI_NOT_FOUND;
> >  
> >  	if (ret != EFI_SUCCESS)
> > -		log_err("Unable to notify StMM for ExitBootServices\n");
> > +		log_err("Unable to notify the MM partition for ExitBootServices\n");
> >  	free(comm_buf);
> >  
> >  	/*
> > -- 
> > 2.17.1
> > 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v5 04/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-10-03 15:22                                       ` Tom Rini
@ 2022-10-14 10:40                                         ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-14 10:40 UTC (permalink / raw)
  To: Tom Rini; +Cc: u-boot, nd

On Mon, Oct 03, 2022 at 11:22:33AM -0400, Tom Rini wrote:
> On Mon, Oct 03, 2022 at 10:49:23AM +0200, Jens Wiklander wrote:
> > On Mon, Sep 26, 2022 at 03:08:21PM +0100, Abdellatif El Khlifi wrote:
> [snip]
> > > diff --git a/doc/README.ffa.drv b/doc/README.ffa.drv
> > > new file mode 100644
> > > index 0000000000..1c0a33deb8
> > > --- /dev/null
> > > +++ b/doc/README.ffa.drv
> > > @@ -0,0 +1,160 @@
> > > +Arm FF-A Driver
> > > +====================
> > > +
> > > +Introduction
> > > +--------------------
> > > +
> > > +FF-A stands for Firmware Framework for Arm A-profile processors.
> > > +
> > > +FF-A specifies interfaces that enable a pair of software sandboxes to communicate with each other. A sandbox aka partition could
> > > +be a VM in the Normal or Secure world, an application in S-EL0, or a Trusted OS in S-EL1.
> > 
> > These lines are a bit long, from the coding guide lines:
> > The preferred limit on the length of a single line is 80 columns.
> 
> Line length isn't a huge problem, we follow what the linux kernel allows
> these days.  But, this needs to be in proper sphinx format, under
> doc/arch perhaps (unless Heinrich has another idea) and 'make htmldocs'
> must pass (I see a lot of formatting errors that will get tripped up on
> and fail).

In patchset v6, FF-A documentation is at doc/arch/arm64.ffa.rst and comes with Sphinx format.
'make htmldocs' passes.

> 
> -- 
> Tom



^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 00/10] introduce Arm FF-A support
  2022-10-13 12:07                                     ` [PATCH v6 00/10] introduce Arm FF-A support Ilias Apalodimas
@ 2022-10-14 10:44                                       ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-14 10:44 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, nd

On Thu, Oct 13, 2022 at 03:07:39PM +0300, Ilias Apalodimas wrote:
> Hi Abdellatif,
> 
> On Thu, Oct 13, 2022 at 11:38:47AM +0100, Abdellatif El Khlifi wrote:
> > Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [6].
> > 
> > FF-A describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World. These interfaces enable a pair of
> > software sandboxes to communicate with each other. A sandbox aka partition could
> > be a VM in the Normal or Secure world, an application in S-EL0, or a
> > Trusted OS in S-EL1.
> > 
> > The FF-A transport is implemented as a data bus and a core driver is provided.
> > 
> > The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> > 
> > - Discover the presence of secure partitions (SPs) of interest
> > - Access an SP's service through communication protocols
> >   e.g. EFI MM communication protocol
> > 
> > The FF-A support provides the following features:
> > 
> > - Being generic by design and can be used by any Arm 64-bit platform
> > - The FF-A core driver
> > - The FF-A bus is discoverable on demand at runtime
> > - The driver provides callbacks to be used by clients to access the FF-A bus
> > - FF-A driver can be compiled and used without EFI
> > - Support for SMCCCv1.2 x0-x17 registers
> > - A new command called armffa is provided as an example of how to access the
> >   FF-A bus
> > - An FF-A Sandbox driver is provided with test cases
> > - Support for FF-A MM communication
> > - Enabling FF-A and MM communication in Corstone1000 platform
> > 
> > For more details about the FF-A core driver please refer to [7].
> > 
> > Please find at [8] an example of the expected boot logs when enabling
> > FF-A support for a platform. In this example the platform is
> > Corstone1000. But it can be any Arm 64-bit platform.
> > 
> > Changelog of the major changes:
> > ===========================
> > 
> > v6:
> > 
> > * remove clearing x0-x17 registers after SMC calls
> > * drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
> 
> Thanks! This makes the whole process way way easier.  I am bit overloaded
> atm but I'll try squeezing in reviewing these patches

You're welcome! Happy to improve the patchset :)

> 
> > * drop discovery from initcalls (discovery will be on demand by FF-A users)
> > * add FF-A runtime discovery at MM communication level
> > * update the documentation and move it to doc/arch/arm64.ffa.rst
> > 
> > v5: [5]
> > 
> > * move changelogs in each commit to the changes section
> > 
> > v4: [4]
> > 
> > * add FF-A support README (doc/README.ffa.drv)
> > * improving error handling by mapping the FF-A errors to standard errors
> >   and logs
> > * replacing panics with an error log
> > * align sandbox driver and tests with the new FF-A driver interfaces
> >  and new way of error handling
>  
> [...]
> 
> Thanks
> /Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v5 09/10] arm_ffa: introduce FF-A MM communication
  2022-10-14 10:38                                       ` Abdellatif El Khlifi
@ 2022-10-14 15:55                                         ` Simon Glass
  2022-10-14 16:08                                           ` Ilias Apalodimas
  2022-10-17 14:15                                           ` Abdellatif El Khlifi
  0 siblings, 2 replies; 478+ messages in thread
From: Simon Glass @ 2022-10-14 15:55 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: Ilias Apalodimas, u-boot, nd

Hi,

On Fri, 14 Oct 2022 at 04:38, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> On Thu, Sep 29, 2022 at 12:32:42PM +0300, Ilias Apalodimas wrote:
> > Hi Abdellatif,
> >
> > > --- a/arch/arm/cpu/armv8/cache.S
> > > +++ b/arch/arm/cpu/armv8/cache.S
> > > @@ -3,6 +3,9 @@
> > >   * (C) Copyright 2013
> > >   * David Feng <fenghua@phytium.com.cn>
> > >   *
> > > + * (C) Copyright 2022 ARM Limited
> > > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > + *
> > >   * This file is based on sample code from ARMv8 ARM.
> > >   */
> > >
> > > @@ -21,7 +24,11 @@
> > >   * x1: 0 clean & invalidate, 1 invalidate only
> > >   * x2~x9: clobbered
> > >   */
> > > +#ifdef CONFIG_EFI_LOADER
> > > +.pushsection .text.efi_runtime, "ax"
> >
> > Maybe we discussed this in the past and I forgot,  but why would you need
> > __asm_dcache_level, __asm_dcache_all, __asm_invalidate_dcache_alla etc in
> > the runtime section ?
>
> Because cache invalidation needs to be done at ffa_mm_communicate() level (v4 patchset).
> That code is runtime compatible so all the called functions must be under .text.efi_runtime
>
> However, since we agreed to drop EFI runtime support from the patchset, v6 patchset takes
> care of that.
>
> >
> > > +#else
> > >  .pushsection .text.__asm_dcache_level, "ax"
> > > +#endif
> > >  ENTRY(__asm_dcache_level)
> > >     lsl     x12, x0, #1
> > >     msr     csselr_el1, x12         /* select cache level */
> > > @@ -65,7 +72,11 @@ ENDPROC(__asm_dcache_level)
> > >   *
> > >   * flush or invalidate all data cache by SET/WAY.
> > >   */
> > > +#ifdef CONFIG_EFI_LOADER
> > > +.pushsection .text.efi_runtime, "ax"
> > > +#else
> > >  .pushsection .text.__asm_dcache_all, "ax"
> > > +#endif
> > >  ENTRY(__asm_dcache_all)
> > >     mov     x1, x0
> > >     dsb     sy
> > > @@ -109,7 +120,11 @@ ENTRY(__asm_flush_dcache_all)
> > >  ENDPROC(__asm_flush_dcache_all)
> > >  .popsection
> > >
> > > +#ifdef CONFIG_EFI_LOADER
> > > +.pushsection .text.efi_runtime, "ax"
> > > +#else
> > >  .pushsection .text.__asm_invalidate_dcache_all, "ax"
> > > +#endif
> > >  ENTRY(__asm_invalidate_dcache_all)
> > >     mov     x0, #0x1
> > >     b       __asm_dcache_all
> > > @@ -182,7 +197,11 @@ ENTRY(__asm_invalidate_icache_all)
> > >  ENDPROC(__asm_invalidate_icache_all)
> > >  .popsection
> > >
> > > +#ifdef CONFIG_EFI_LOADER
> > > +.pushsection .text.efi_runtime, "ax"
> > > +#else
> > >  .pushsection .text.__asm_invalidate_l3_dcache, "ax"
> > > +#endif
> > >  WEAK(__asm_invalidate_l3_dcache)
> > >     mov     x0, #0                  /* return status as success */
> > >     ret
> > > diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
> > > index e4736e5643..45f57372c2 100644
> > > --- a/arch/arm/cpu/armv8/cache_v8.c
> > > +++ b/arch/arm/cpu/armv8/cache_v8.c
> > > @@ -5,10 +5,14 @@
> > >   *
> > >   * (C) Copyright 2016
> > >   * Alexander Graf <agraf@suse.de>
> > > + *
> > > + * (C) Copyright 2022 ARM Limited
> > > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > >   */
> > >
> > >  #include <common.h>
> > >  #include <cpu_func.h>
> > > +#include <efi_loader.h>
> > >  #include <hang.h>
> > >  #include <log.h>
> > >  #include <asm/cache.h>
> > > @@ -445,7 +449,7 @@ __weak void mmu_setup(void)
> > >  /*
> > >   * Performs a invalidation of the entire data cache at all levels
> > >   */
> > > -void invalidate_dcache_all(void)
> > > +void __efi_runtime invalidate_dcache_all(void)
> > >  {
> > >     __asm_invalidate_dcache_all();
> > >     __asm_invalidate_l3_dcache();
> > > diff --git a/include/mm_communication.h b/include/mm_communication.h
> > > index e65fbde60d..fe9104c56d 100644
> > > --- a/include/mm_communication.h
> >
> > [...]
> >
> > >   * always begin with efi_mm_communicate_header.
> > >   */
> > > -struct __packed efi_mm_communicate_header {
> > > +struct efi_mm_communicate_header {
> > >     efi_guid_t header_guid;
> > >     size_t     message_len;
> > >     u8         data[];
> > > @@ -145,7 +150,7 @@ struct smm_variable_communicate_header {
> > >   * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
> > >   *
> > >   */
> > > -struct smm_variable_access {
> > > +struct __packed smm_variable_access {
> >
> > You are randomly adding and deleting __packed cwin both structs. But you can't do that.
> > Those structs are defined in StandAloneMM.  This is the reason each struct
> > description has the corresponding EDK2 definition.
>
> Thanks for the comment.
>
> However, we are not setting randomly the __packed keyword. There is a good reason for that.
> It has been explained before in this reply [1]. Basically it's because of data padding issues
> breaking the communication between u-boot and secure world (Optee).
>
> When upgrading Optee to v3.18, no issues anymore.
>
> The __packed changes have been dropped in patchset v6.
>
> [1]: https://lore.kernel.org/all/20220926105620.GA22382@e121910.cambridge.arm.com/

That is the Linux mailing list. I cannot see any reason to add
__packed to this struct as it is already set up that way.

Also efi_mm_communicate_header is really long. I suggest efi_mm_hdr or
efi_mm_comms_hdr

Why are you using SMM on ARM? Isn't that an Intel thing?

[..]

Regards,
SImon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v5 09/10] arm_ffa: introduce FF-A MM communication
  2022-10-14 15:55                                         ` Simon Glass
@ 2022-10-14 16:08                                           ` Ilias Apalodimas
  2022-10-17 14:15                                           ` Abdellatif El Khlifi
  1 sibling, 0 replies; 478+ messages in thread
From: Ilias Apalodimas @ 2022-10-14 16:08 UTC (permalink / raw)
  To: Simon Glass; +Cc: Abdellatif El Khlifi, u-boot, nd

Hi Simon,

[...]

> > >
> > > >   * always begin with efi_mm_communicate_header.
> > > >   */
> > > > -struct __packed efi_mm_communicate_header {
> > > > +struct efi_mm_communicate_header {
> > > >     efi_guid_t header_guid;
> > > >     size_t     message_len;
> > > >     u8         data[];
> > > > @@ -145,7 +150,7 @@ struct smm_variable_communicate_header {
> > > >   * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
> > > >   *
> > > >   */
> > > > -struct smm_variable_access {
> > > > +struct __packed smm_variable_access {
> > >
> > > You are randomly adding and deleting __packed cwin both structs. But you can't do that.
> > > Those structs are defined in StandAloneMM.  This is the reason each struct
> > > description has the corresponding EDK2 definition.
> >
> > Thanks for the comment.
> >
> > However, we are not setting randomly the __packed keyword. There is a good reason for that.
> > It has been explained before in this reply [1]. Basically it's because of data padding issues
> > breaking the communication between u-boot and secure world (Optee).
> >
> > When upgrading Optee to v3.18, no issues anymore.
> >
> > The __packed changes have been dropped in patchset v6.
> >
> > [1]: https://lore.kernel.org/all/20220926105620.GA22382@e121910.cambridge.arm.com/
>
> That is the Linux mailing list. I cannot see any reason to add
> __packed to this struct as it is already set up that way.
>
> Also efi_mm_communicate_header is really long. I suggest efi_mm_hdr or
> efi_mm_comms_hdr
>
> Why are you using SMM on ARM? Isn't that an Intel thing?

This is due to the fact that we run StandAloneMM, which is a specific
EDK2 'package' to handle the variables in Arm secure world. There's a
really long explanation on how that works here [0] in case you are
interested.  The naming is a bit unfortunate, but since we have to
read it and reason about the EDK2 API in future versions, I suggest
keeping it as close to the original as possible.  Alternatively we
could just add a comment with the EDK2 equivalent, but in any case,
the change you are request is out of scope for this patchset.


[0] https://www.linaro.org/blog/protected-uefi-variables-with-u-boot/

Regards
/Ilias
>
> [..]
>
> Regards,
> SImon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v5 09/10] arm_ffa: introduce FF-A MM communication
  2022-10-14 15:55                                         ` Simon Glass
  2022-10-14 16:08                                           ` Ilias Apalodimas
@ 2022-10-17 14:15                                           ` Abdellatif El Khlifi
  1 sibling, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-17 14:15 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, nd

On Fri, Oct 14, 2022 at 09:55:59AM -0600, Simon Glass wrote:
> Hi,
> 
> On Fri, 14 Oct 2022 at 04:38, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > On Thu, Sep 29, 2022 at 12:32:42PM +0300, Ilias Apalodimas wrote:
> > > Hi Abdellatif,
> > >
> > > > --- a/arch/arm/cpu/armv8/cache.S
> > > > +++ b/arch/arm/cpu/armv8/cache.S
> > > > @@ -3,6 +3,9 @@
> > > >   * (C) Copyright 2013
> > > >   * David Feng <fenghua@phytium.com.cn>
> > > >   *
> > > > + * (C) Copyright 2022 ARM Limited
> > > > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > + *
> > > >   * This file is based on sample code from ARMv8 ARM.
> > > >   */
> > > >
> > > > @@ -21,7 +24,11 @@
> > > >   * x1: 0 clean & invalidate, 1 invalidate only
> > > >   * x2~x9: clobbered
> > > >   */
> > > > +#ifdef CONFIG_EFI_LOADER
> > > > +.pushsection .text.efi_runtime, "ax"
> > >
> > > Maybe we discussed this in the past and I forgot,  but why would you need
> > > __asm_dcache_level, __asm_dcache_all, __asm_invalidate_dcache_alla etc in
> > > the runtime section ?
> >
> > Because cache invalidation needs to be done at ffa_mm_communicate() level (v4 patchset).
> > That code is runtime compatible so all the called functions must be under .text.efi_runtime
> >
> > However, since we agreed to drop EFI runtime support from the patchset, v6 patchset takes
> > care of that.
> >
> > >
> > > > +#else
> > > >  .pushsection .text.__asm_dcache_level, "ax"
> > > > +#endif
> > > >  ENTRY(__asm_dcache_level)
> > > >     lsl     x12, x0, #1
> > > >     msr     csselr_el1, x12         /* select cache level */
> > > > @@ -65,7 +72,11 @@ ENDPROC(__asm_dcache_level)
> > > >   *
> > > >   * flush or invalidate all data cache by SET/WAY.
> > > >   */
> > > > +#ifdef CONFIG_EFI_LOADER
> > > > +.pushsection .text.efi_runtime, "ax"
> > > > +#else
> > > >  .pushsection .text.__asm_dcache_all, "ax"
> > > > +#endif
> > > >  ENTRY(__asm_dcache_all)
> > > >     mov     x1, x0
> > > >     dsb     sy
> > > > @@ -109,7 +120,11 @@ ENTRY(__asm_flush_dcache_all)
> > > >  ENDPROC(__asm_flush_dcache_all)
> > > >  .popsection
> > > >
> > > > +#ifdef CONFIG_EFI_LOADER
> > > > +.pushsection .text.efi_runtime, "ax"
> > > > +#else
> > > >  .pushsection .text.__asm_invalidate_dcache_all, "ax"
> > > > +#endif
> > > >  ENTRY(__asm_invalidate_dcache_all)
> > > >     mov     x0, #0x1
> > > >     b       __asm_dcache_all
> > > > @@ -182,7 +197,11 @@ ENTRY(__asm_invalidate_icache_all)
> > > >  ENDPROC(__asm_invalidate_icache_all)
> > > >  .popsection
> > > >
> > > > +#ifdef CONFIG_EFI_LOADER
> > > > +.pushsection .text.efi_runtime, "ax"
> > > > +#else
> > > >  .pushsection .text.__asm_invalidate_l3_dcache, "ax"
> > > > +#endif
> > > >  WEAK(__asm_invalidate_l3_dcache)
> > > >     mov     x0, #0                  /* return status as success */
> > > >     ret
> > > > diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
> > > > index e4736e5643..45f57372c2 100644
> > > > --- a/arch/arm/cpu/armv8/cache_v8.c
> > > > +++ b/arch/arm/cpu/armv8/cache_v8.c
> > > > @@ -5,10 +5,14 @@
> > > >   *
> > > >   * (C) Copyright 2016
> > > >   * Alexander Graf <agraf@suse.de>
> > > > + *
> > > > + * (C) Copyright 2022 ARM Limited
> > > > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > >   */
> > > >
> > > >  #include <common.h>
> > > >  #include <cpu_func.h>
> > > > +#include <efi_loader.h>
> > > >  #include <hang.h>
> > > >  #include <log.h>
> > > >  #include <asm/cache.h>
> > > > @@ -445,7 +449,7 @@ __weak void mmu_setup(void)
> > > >  /*
> > > >   * Performs a invalidation of the entire data cache at all levels
> > > >   */
> > > > -void invalidate_dcache_all(void)
> > > > +void __efi_runtime invalidate_dcache_all(void)
> > > >  {
> > > >     __asm_invalidate_dcache_all();
> > > >     __asm_invalidate_l3_dcache();
> > > > diff --git a/include/mm_communication.h b/include/mm_communication.h
> > > > index e65fbde60d..fe9104c56d 100644
> > > > --- a/include/mm_communication.h
> > >
> > > [...]
> > >
> > > >   * always begin with efi_mm_communicate_header.
> > > >   */
> > > > -struct __packed efi_mm_communicate_header {
> > > > +struct efi_mm_communicate_header {
> > > >     efi_guid_t header_guid;
> > > >     size_t     message_len;
> > > >     u8         data[];
> > > > @@ -145,7 +150,7 @@ struct smm_variable_communicate_header {
> > > >   * Defined in EDK2 as SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
> > > >   *
> > > >   */
> > > > -struct smm_variable_access {
> > > > +struct __packed smm_variable_access {
> > >
> > > You are randomly adding and deleting __packed cwin both structs. But you can't do that.
> > > Those structs are defined in StandAloneMM.  This is the reason each struct
> > > description has the corresponding EDK2 definition.
> >
> > Thanks for the comment.
> >
> > However, we are not setting randomly the __packed keyword. There is a good reason for that.
> > It has been explained before in this reply [1]. Basically it's because of data padding issues
> > breaking the communication between u-boot and secure world (Optee).
> >
> > When upgrading Optee to v3.18, no issues anymore.
> >
> > The __packed changes have been dropped in patchset v6.
> >
> > [1]: https://lore.kernel.org/all/20220926105620.GA22382@e121910.cambridge.arm.com/
> 
> That is the Linux mailing list. I cannot see any reason to add

Thanks Simon. The link above is not part of the linux mailing list.
It points to the mirror of the u-boot mailing list under lore.kernel.org

> __packed to this struct as it is already set up that way.
> 
> Also efi_mm_communicate_header is really long. I suggest efi_mm_hdr or
> efi_mm_comms_hdr
> 
> Why are you using SMM on ARM? Isn't that an Intel thing?
> 
> [..]
> 
> Regards,
> SImon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 02/10] lib: uuid: introduce be_uuid_str_to_le_bin function
  2022-10-13 10:38                                     ` [PATCH v6 02/10] lib: uuid: introduce be_uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2022-10-24 12:07                                       ` Ilias Apalodimas
  2022-11-08 10:45                                         ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2022-10-24 12:07 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, jens.wiklander, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong, Drew.Reed

Hi Abdellatif, 

On Thu, Oct 13, 2022 at 11:38:49AM +0100, Abdellatif El Khlifi wrote:
> convert big endian UUID string to little endian buffer

You don't really need the be_ suffix on the declaration, endianness doesn't
apply to strings.  Can't we do something similar to uuid_str_to_bin() and
just convert to LE?

Thanks
/Ilias
> 
> 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>
> 
> ---
> 
> Changelog:
> ===============
> 
> v4:
> 
> * rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
>   a standalone commit (the current)
> 
> v3:
> 
> * introduce ffa_uuid_str_to_bin (provided by
>   arm_ffa: introduce Arm FF-A low-level driver)
> 
> include/uuid.h |  8 +++++++
>  lib/uuid.c     | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 72 insertions(+)
> 
> diff --git a/include/uuid.h b/include/uuid.h
> index 4a4883d3b5..ad3af350f9 100644
> --- a/include/uuid.h
> +++ b/include/uuid.h
> @@ -2,6 +2,8 @@
>  /*
>   * Copyright (C) 2014 Samsung Electronics
>   * Przemyslaw Marczak <p.marczak@samsung.com>
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  #ifndef __UUID_H__
>  #define __UUID_H__
> @@ -44,4 +46,10 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
>  const char *uuid_guid_get_str(const unsigned char *guid_bin);
>  void gen_rand_uuid(unsigned char *uuid_bin);
>  void gen_rand_uuid_str(char *uuid_str, int str_format);
> +
> +/**
> + * be_uuid_str_to_le_bin - Converts a big endian UUID string to a little endian buffer
> + */
> +int be_uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
> +
>  #endif
> diff --git a/lib/uuid.c b/lib/uuid.c
> index 465e1ac38f..15a9ab49d5 100644
> --- a/lib/uuid.c
> +++ b/lib/uuid.c
> @@ -1,6 +1,8 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  /*
>   * Copyright 2011 Calxeda, Inc.
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #include <common.h>
> @@ -346,6 +348,68 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
>  	return 0;
>  }
>  
> +/**
> + * be_uuid_str_to_le_bin - Converts a big endian UUID string to a little endian buffer
> + * @uuid_str:	UUID string in big endian format (36 bytes wide + '/0')
> + * @uuid_bin:	preallocated 16 bytes UUID buffer in little endian format
> + *
> + * UUID string is 36 characters (36 bytes):
> + *
> + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
> + * be		     be	     be	      be      be
> + *
> + * where x is a hexadecimal character. Fields are separated by '-'s.
> + * When converting to a binary UUID, these endianness rules apply:
> + *     be: means the field in the string is considered a big endian hex number
> + *	   and should be converted to little endian binary format
> + *
> + * Return:
> + *
> + *    uuid_bin filled with little endian UUID data
> + *    On success 0 is returned. Otherwise, failure code.
> + */
> +int be_uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
> +{
> +	u16 tmp16 = 0;
> +	u32 tmp32 = 0;
> +	u64 tmp64 = 0;
> +
> +	if (!uuid_str_valid(uuid_str) || !uuid_bin)
> +		return -EINVAL;
> +
> +	/*
> +	 * reverse bytes from big to little endian
> +	 */
> +	tmp32 = simple_strtoul(uuid_str, NULL, 16);
> +	memcpy(uuid_bin, &tmp32, 4);
> +
> +	/*
> +	 * reverse bytes from big to little endian
> +	 */
> +	tmp16 = simple_strtoul(uuid_str + 9, NULL, 16);
> +	memcpy(uuid_bin + 4, &tmp16, 2);
> +
> +	/*
> +	 * reverse bytes from big to little endian
> +	 */
> +	tmp16 = simple_strtoul(uuid_str + 14, NULL, 16);
> +	memcpy(uuid_bin + 6, &tmp16, 2);
> +
> +	/*
> +	 * reverse bytes from big to little endian
> +	 */
> +	tmp16 = simple_strtoul(uuid_str + 19, NULL, 16);
> +	memcpy(uuid_bin + 8, &tmp16, 2);
> +
> +	/*
> +	 * reverse bytes from big to little endian
> +	 */
> +	tmp64 = simple_strtoull(uuid_str + 24, NULL, 16);
> +	memcpy(uuid_bin + 10, (char *)&tmp64, 6);
> +
> +	return 0;
> +}
> +
>  /*
>   * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
>   *
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 04/10] arm_ffa: efi: unmap RX/TX buffers
  2022-10-13 10:38                                     ` [PATCH v6 04/10] arm_ffa: efi: unmap RX/TX buffers Abdellatif El Khlifi
@ 2022-10-24 12:08                                       ` Ilias Apalodimas
  2022-11-08 10:48                                         ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2022-10-24 12:08 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, jens.wiklander, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong, Drew.Reed

On Thu, Oct 13, 2022 at 11:38:51AM +0100, Abdellatif El Khlifi wrote:
> unmap RX/TX buffers at ExitBootServices()
> 
> Unmapping the RX/TX buffers created by u-boot is needed before EFI
> runtime.
> 
> At EFI runtime the linux kernel takes care of allocating its own RX/TX
> buffers and registering them with the secure world.
> 
> Secure world should be using the RX/TX buffers created by the kernel.
> So, RX/TX buffers created by u-boot must be unmapped.
> 
> 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>
> ---
>  lib/efi_loader/efi_boottime.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index a56021559b..2054b33568 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -3,6 +3,9 @@
>   * EFI application boot time services
>   *
>   * Copyright (c) 2016 Alexander Graf
> + *
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #include <common.h>
> @@ -23,6 +26,10 @@
>  #include <asm/setjmp.h>
>  #include <linux/libfdt_env.h>
>  
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
> +#include <arm_ffa.h>
> +#endif
> +
>  DECLARE_GLOBAL_DATA_PTR;
>  
>  /* Task priority level */
> @@ -2178,6 +2185,14 @@ 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)
> +		/* 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");

Just do log_err() here and get rid of the else

> +		else
> +			debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
> +#endif
> +
>  	/* Patch out unsupported runtime function */
>  	efi_runtime_detach();
>  
> -- 
> 2.17.1
> 

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  2022-10-13 10:38                                     ` [PATCH v6 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2022-10-24 12:10                                       ` Ilias Apalodimas
  2022-11-08 10:53                                         ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2022-10-24 12:10 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, jens.wiklander, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong, Drew.Reed

Hi Abdellatif
On Thu, Oct 13, 2022 at 11:38:54AM +0100, Abdellatif El Khlifi wrote:
> Add functional test cases for the FF-A core driver
> 
> These tests rely on the FF-A Sandbox driver which helps in
>  inspecting the FF-A core driver.

This looks ok from me, but I'd prefer Simon having a quick look, since I am
not an expert when it comes to sandbox and testing 

Thanks
/Ilias
> 
> 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>
> 
> ---
> 
> Changelog:
> ===============
> 
> v4: align sandbox tests with the new FF-A driver interfaces
>  and new way of error handling
> 
> v1: introduce sandbox tests
> 
>  MAINTAINERS      |   1 +
>  test/dm/Makefile |   2 +
>  test/dm/ffa.c    | 394 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 397 insertions(+)
>  create mode 100644 test/dm/ffa.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 598ae76e16..bf198f4ce1 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -256,6 +256,7 @@ F:	doc/arch/arm64.ffa.rst
>  F:	drivers/firmware/arm-ffa/
>  F:	include/arm_ffa.h
>  F:	include/sandbox_arm_ffa.h
> +F:	test/dm/ffa.c
>  
>  ARM FREESCALE IMX
>  M:	Stefano Babic <sbabic@denx.de>
> diff --git a/test/dm/Makefile b/test/dm/Makefile
> index 5178daa7cf..e5bc4b4bd6 100644
> --- a/test/dm/Makefile
> +++ b/test/dm/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0+
>  #
>  # Copyright (c) 2013 Google, Inc
> +# (C) Copyright 2022 ARM Limited
>  
>  obj-$(CONFIG_UT_DM) += test-dm.o
>  
> @@ -81,6 +82,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
>  obj-$(CONFIG_ACPI_PMC) += pmc.o
>  obj-$(CONFIG_DM_PMIC) += pmic.o
>  obj-$(CONFIG_DM_PWM) += pwm.o
> +obj-$(CONFIG_SANDBOX_FFA) += ffa.o
>  obj-$(CONFIG_QFW) += qfw.o
>  obj-$(CONFIG_RAM) += ram.o
>  obj-y += regmap.o
> diff --git a/test/dm/ffa.c b/test/dm/ffa.c
> new file mode 100644
> index 0000000000..052d5fc3f4
> --- /dev/null
> +++ b/test/dm/ffa.c
> @@ -0,0 +1,394 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Functional tests for UCLASS_FFA  class
> + *
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include <common.h>
> +#include <console.h>
> +#include <dm.h>
> +#include <dm/test.h>
> +#include "../../drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h"
> +#include <sandbox_arm_ffa.h>
> +#include <test/test.h>
> +#include <test/ut.h>
> +
> +/* Macros */
> +
> +#define LOG_MSG_SZ (100)
> +#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
> +
> +/* Functional tests for the UCLASS_FFA */
> +
> +static int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
> +{
> +	char cmd[LOG_CMD_SZ] = {0};
> +
> +	console_record_reset();
> +
> +	snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
> +	run_command(cmd, 0);
> +
> +	ut_assert_console_end();
> +
> +	return CMD_RET_SUCCESS;
> +}
> +
> +static int check_fwk_version(struct ffa_prvdata *prvdata, struct sandbox_ffa_prvdata *sdx_prvdata,
> +			     struct unit_test_state *uts)
> +{
> +	if (prvdata->fwk_version != sdx_prvdata->fwk_version) {
> +		char msg[LOG_MSG_SZ] = {0};
> +
> +		snprintf(msg, LOG_MSG_SZ,
> +			 "[%s]: Error: framework version: core = 0x%x , sandbox  = 0x%x", __func__,
> +			 prvdata->fwk_version,
> +			sdx_prvdata->fwk_version);
> +
> +		dm_test_ffa_log(uts, msg);
> +		return CMD_RET_FAILURE;
> +	}
> +	return CMD_RET_SUCCESS;
> +}
> +
> +static int check_endpoint_id(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
> +{
> +	if (prvdata->id) {
> +		char msg[LOG_MSG_SZ] = {0};
> +
> +		snprintf(msg, LOG_MSG_SZ,
> +			 "[%s]: Error: endpoint id: core = 0x%x", __func__, prvdata->id);
> +		dm_test_ffa_log(uts, msg);
> +		return CMD_RET_FAILURE;
> +	}
> +	return CMD_RET_SUCCESS;
> +}
> +
> +static int check_core_dev(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
> +{
> +	if (!prvdata->dev) {
> +		char msg[LOG_MSG_SZ] = {0};
> +
> +		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: core device NULL", __func__);
> +		dm_test_ffa_log(uts, msg);
> +		return CMD_RET_FAILURE;
> +	}
> +	return CMD_RET_SUCCESS;
> +}
> +
> +static int check_sandbox_dev(struct sandbox_ffa_prvdata *sdx_prvdata, struct unit_test_state *uts)
> +{
> +	if (!sdx_prvdata->dev) {
> +		char msg[LOG_MSG_SZ] = {0};
> +
> +		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: sandbox device NULL", __func__);
> +		dm_test_ffa_log(uts, msg);
> +		return CMD_RET_FAILURE;
> +	}
> +	return CMD_RET_SUCCESS;
> +}
> +
> +static int check_rxtxbuf(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
> +{
> +	if (!prvdata->pair.rxbuf && prvdata->pair.txbuf) {
> +		char msg[LOG_MSG_SZ] = {0};
> +
> +		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = 0x%llx txbuf = 0x%llx", __func__,
> +			 prvdata->pair.rxbuf,
> +			 prvdata->pair.txbuf);
> +		dm_test_ffa_log(uts, msg);
> +		return CMD_RET_FAILURE;
> +	}
> +	return CMD_RET_SUCCESS;
> +}
> +
> +static int check_features(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
> +{
> +	char msg[LOG_MSG_SZ] = {0};
> +
> +	if (prvdata->pair.rxtx_min_pages != RXTX_4K &&
> +	    prvdata->pair.rxtx_min_pages != RXTX_16K &&
> +	    prvdata->pair.rxtx_min_pages != RXTX_64K) {
> +		snprintf(msg,
> +			 LOG_MSG_SZ,
> +			 "[%s]: Error: FFA_RXTX_MAP features = 0x%lx",
> +			 __func__,
> +			 prvdata->pair.rxtx_min_pages);
> +		dm_test_ffa_log(uts, msg);
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	return CMD_RET_SUCCESS;
> +}
> +
> +static int check_rxbuf_mapped_flag(u32 queried_func_id,
> +				   u8 rxbuf_mapped,
> +				   struct unit_test_state *uts)
> +{
> +	char msg[LOG_MSG_SZ] = {0};
> +
> +	switch (queried_func_id) {
> +	case FFA_RXTX_MAP:
> +	{
> +		if (rxbuf_mapped)
> +			return CMD_RET_SUCCESS;
> +		break;
> +	}
> +	case FFA_RXTX_UNMAP:
> +	{
> +		if (!rxbuf_mapped)
> +			return CMD_RET_SUCCESS;
> +		break;
> +	}
> +	default:
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__,
> +		 (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP"));
> +	dm_test_ffa_log(uts, msg);
> +
> +	return CMD_RET_FAILURE;
> +}
> +
> +static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
> +{
> +	if (rxbuf_owned) {
> +		char msg[LOG_MSG_SZ] = {0};
> +
> +		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__);
> +		dm_test_ffa_log(uts, msg);
> +		return CMD_RET_FAILURE;
> +	}
> +	return CMD_RET_SUCCESS;
> +}
> +
> +static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
> +{
> +	struct ffa_send_direct_data msg = {0};
> +	u8 cnt;
> +
> +	ut_assertok(ffa_bus_ops_get()->sync_send_receive(part_id, &msg));
> +
> +	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
> +		ut_assertok(((u64 *)&msg)[cnt] != 0xffffffffffffffff);
> +
> +	return CMD_RET_SUCCESS;
> +}
> +
> +static int test_partitions_and_comms(const char *service_uuid,
> +				     struct sandbox_ffa_prvdata *sdx_prvdata,
> +				     struct unit_test_state *uts)
> +{
> +	u32 count = 0, size = 0;
> +	struct ffa_partition_info *parts_info;
> +	u32 info_idx, exp_info_idx;
> +	int ret;
> +
> +	/*
> +	 * get from the driver the count of the SPs matching the UUID
> +	 */
> +	ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &count, NULL);
> +	/* make sure partitions are detected */
> +	ut_assertok(ret != 0);
> +	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
> +
> +	/*
> +	 * pre-allocate a buffer to be filled by the driver
> +	 * with	 ffa_partition_info structs
> +	 */
> +
> +	parts_info = calloc(count, sizeof(struct ffa_partition_info));
> +	ut_assertok(!parts_info);
> +
> +	size = count * sizeof(struct ffa_partition_info);
> +
> +	/*
> +	 * ask the driver to fill the buffer with the SPs info
> +	 */
> +	ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &size, parts_info);
> +	if (ret != 0) {
> +		free(parts_info);
> +		ut_assertok(ret != 0);
> +	}
> +
> +	/*
> +	 * SPs found , verify the partitions information
> +	 */
> +
> +	ret = CMD_RET_FAILURE;
> +
> +	for (info_idx = 0; info_idx < count ; info_idx++) {
> +		for (exp_info_idx = 0;
> +		     exp_info_idx < sdx_prvdata->partitions.count;
> +		     exp_info_idx++) {
> +			if (parts_info[info_idx].id ==
> +			   sdx_prvdata->partitions.descs[exp_info_idx].info.id) {
> +				ret = memcmp(&parts_info[info_idx],
> +					     &sdx_prvdata->partitions.descs[exp_info_idx]
> +					     .info,
> +					     sizeof(struct ffa_partition_info));
> +				if (ret)
> +					free(parts_info);
> +				ut_assertok(ret != 0);
> +				/* send and receive data from the current partition */
> +				test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
> +			}
> +			ret = CMD_RET_SUCCESS;
> +		}
> +	}
> +
> +	free(parts_info);
> +
> +	/* Verify  expected partitions found in the emulated secure world*/
> +	ut_assertok(ret != CMD_RET_SUCCESS);
> +
> +	return CMD_RET_SUCCESS;
> +}
> +
> +static int dm_test_ffa_ack(struct unit_test_state *uts)
> +{
> +	struct ffa_prvdata *prvdata = NULL;
> +	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
> +	struct ffa_sandbox_data func_data = {0};
> +	u8 rxbuf_flag = 0;
> +	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
> +	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
> +	int ret;
> +
> +	/*  test probing FF-A devices */
> +	ut_assertok(ffa_bus_discover());
> +
> +	/* get a pointer to the FF-A core and sandbox drivers private data */
> +	func_data.data0 = &prvdata;
> +	func_data.data0_size = sizeof(prvdata);
> +	func_data.data1 = &sdx_prvdata;
> +	func_data.data1_size = sizeof(sdx_prvdata);
> +
> +	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
> +
> +	/* make sure private data pointers are retrieved */
> +	ut_assertok(prvdata == 0);
> +	ut_assertok(sdx_prvdata == 0);
> +
> +	/* make sure dev devices created */
> +	ut_assertok(check_core_dev(prvdata, uts));
> +	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
> +
> +	/* test FFA_VERSION */
> +	ut_assertok(check_fwk_version(prvdata, sdx_prvdata, uts));
> +
> +	/* test FFA_ID_GET */
> +	ut_assertok(check_endpoint_id(prvdata, uts));
> +
> +	/* test FFA_FEATURES */
> +	ut_assertok(check_features(prvdata, uts));
> +
> +	/*  test core RX/TX buffers */
> +	ut_assertok(check_rxtxbuf(prvdata, uts));
> +
> +	/* test FFA_RXTX_MAP */
> +	func_data.data0 = &rxbuf_flag;
> +	func_data.data0_size = sizeof(rxbuf_flag);
> +
> +	rxbuf_flag = 0;
> +	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_MAP, &func_data));
> +	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts));
> +
> +	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
> +	ret = test_partitions_and_comms(svc1_uuid, sdx_prvdata, uts);
> +	ut_assertok(ret != CMD_RET_SUCCESS);
> +
> +	/* test FFA_RX_RELEASE */
> +	rxbuf_flag = 1;
> +	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
> +	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
> +
> +	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
> +	ret = test_partitions_and_comms(svc2_uuid, sdx_prvdata, uts);
> +	ut_assertok(ret != CMD_RET_SUCCESS);
> +
> +	/* test FFA_RX_RELEASE */
> +	rxbuf_flag = 1;
> +	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
> +	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
> +
> +	/* test FFA_RXTX_UNMAP */
> +	ut_assertok(ffa_bus_ops_get()->rxtx_unmap());
> +
> +	rxbuf_flag = 1;
> +	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_UNMAP, &func_data));
> +	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts));
> +
> +	return CMD_RET_SUCCESS;
> +}
> +
> +DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
> +
> +static int dm_test_ffa_nack(struct unit_test_state *uts)
> +{
> +	struct ffa_prvdata *prvdata = NULL;
> +	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
> +	struct ffa_sandbox_data func_data = {0};
> +	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
> +	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
> +	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
> +	struct ffa_send_direct_data msg = {0};
> +	int ret;
> +	u32 count = 0;
> +	u16 part_id = 0;
> +
> +	/*  test probing FF-A devices */
> +	ut_assertok(ffa_bus_discover());
> +
> +	/* get a pointer to the FF-A core and sandbox drivers private data */
> +	func_data.data0 = &prvdata;
> +	func_data.data0_size = sizeof(prvdata);
> +	func_data.data1 = &sdx_prvdata;
> +	func_data.data1_size = sizeof(sdx_prvdata);
> +
> +	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
> +
> +	/* make sure private data pointers are retrieved */
> +	ut_assertok(prvdata == 0);
> +	ut_assertok(sdx_prvdata == 0);
> +
> +	/* make sure dev devices created */
> +	ut_assertok(check_core_dev(prvdata, uts));
> +	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
> +
> +	/* query partitions count using  invalid arguments  */
> +	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, NULL, NULL);
> +	ut_assertok(ret != -EINVAL);
> +
> +	/* query partitions count using an invalid UUID  string */
> +	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid_str, &count, NULL);
> +	ut_assertok(ret != -EINVAL);
> +
> +	/* query partitions count using an invalid UUID (no matching SP) */
> +	count = 0;
> +	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, &count, NULL);
> +	ut_assertok(count != 0);
> +
> +	/* query partitions count using a valid UUID  */
> +	count = 0;
> +	ret = ffa_bus_ops_get()->partition_info_get(valid_svc_uuid, &count, NULL);
> +	/* make sure partitions are detected */
> +	ut_assertok(ret != 0);
> +	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
> +
> +	/* send data to an invalid partition */
> +	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
> +	ut_assertok(ret != -EINVAL);
> +
> +	/* send data to a valid partition */
> +	part_id = prvdata->partitions.descs[0].info.id;
> +	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
> +	ut_assertok(ret != 0);
> +
> +	return CMD_RET_SUCCESS;
> +}
> +
> +DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2022-10-13 10:38                                     ` [PATCH v6 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
@ 2022-10-24 12:13                                       ` Ilias Apalodimas
  2022-11-08 11:01                                         ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2022-10-24 12:13 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, jens.wiklander, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong, Drew.Reed

On Thu, Oct 13, 2022 at 11:38:57AM +0100, Abdellatif El Khlifi wrote:
> turn on EFI MM communication
> 
> On corstone1000 platform MM communication between u-boot
> and the secure world (Optee) is done using the FF-A bus.
> 
> 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>
> 
> ---
> 
> Changelog:
> ===============
> 
> v6:
> 
> * corstone-1000: enable optee driver
> * corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig
> 
> v4:
> 
> * corstone-1000: turn on EFI MM communication
> 
>  configs/corstone1000_defconfig | 4 ++++
>  include/configs/corstone1000.h | 9 +++++++++
>  2 files changed, 13 insertions(+)
> 
> diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
> index ed2e0fe70a..4c9ed9fb71 100644
> --- a/configs/corstone1000_defconfig
> +++ b/configs/corstone1000_defconfig
> @@ -52,3 +52,7 @@ CONFIG_DM_SERIAL=y
>  CONFIG_USB=y
>  CONFIG_USB_ISP1760=y
>  CONFIG_ERRNO_STR=y
> +CONFIG_EFI_MM_COMM_TEE=y
> +CONFIG_TEE=y
> +CONFIG_OPTEE=y
> +CONFIG_ARM_FFA_TRANSPORT=y
> diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
> index 8e0230c135..997d0bebaf 100644
> --- a/include/configs/corstone1000.h
> +++ b/include/configs/corstone1000.h
> @@ -14,6 +14,15 @@
>  
>  #include <linux/sizes.h>
>  
> +#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
> +
> +/*
> + * shared buffer physical address used for communication between
> + * u-boot and the MM SP
> + */
> +#define FFA_SHARED_MM_BUFFER_ADDR	(0x023F8000)
> +#define FFA_SHARED_MM_BUFFER_OFFSET	(0)

The rest of the declarations on this file don't have () so please remove
them.  Also is FFA_SHARED_MM_BUFFER_ADDR used anywhere that would justify UL
in the suffix?

Thanks
/Ilias
> +
>  #define V2M_BASE		0x80000000
>  
>  #define CONFIG_PL011_CLOCK	50000000
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 09/10] arm_ffa: efi: introduce FF-A MM communication
  2022-10-13 10:38                                     ` [PATCH v6 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2022-10-24 12:30                                       ` Ilias Apalodimas
  2022-11-08 10:58                                         ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2022-10-24 12:30 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, jens.wiklander, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong, Drew.Reed, Gowtham Suresh Kumar

Hi Abdellatif,

[...]

>  
>  #include <common.h>
> @@ -15,6 +17,36 @@
>  #include <malloc.h>
>  #include <mm_communication.h>
>  
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +
> +#include <arm_ffa.h>
> +#include <cpu_func.h>
> +#include <mapmem.h>
> +
> +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> +#warning "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_SIZE 0
> +#endif
> +
> +#ifndef FFA_SHARED_MM_BUFFER_OFFSET
> +#warning "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_OFFSET 0
> +#endif
> +
> +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> +#warning "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_ADDR 0
> +#endif

Is the device going to work with these defaults? I am assuming not, so
isn't better to treat this as compile time errors?

> +
> +/* MM return codes */
> +#define MM_SUCCESS (0)
> +
> +const char *mm_sp_svc_uuid = MM_SP_UUID;

static ?

> +
> +static u16 mm_sp_id;
> +
> +#endif
> +
>  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
>  static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
>  static efi_uintn_t max_payload_size;	/* func + data */
> @@ -24,6 +56,7 @@ struct mm_connection {
>  	u32 session;
>  };
>  
> +#if (IS_ENABLED(CONFIG_OPTEE))
>  /**
>   * get_connection() - Retrieve OP-TEE session for a specific UUID.
>   *
> @@ -143,13 +176,224 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
>  
>  	return ret;
>  }
> +#endif
> +
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +
> +/**
> + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> + *
> + * Notifies the MM partition in the trusted world that
> + * data is available in the shared buffer.
> + * This is a blocking call during which trusted world has exclusive access
> + * to the MM shared buffer.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_notify_mm_sp(void)
> +{
> +	struct ffa_send_direct_data msg = {0};
> +	int ret;
> +	int sp_event_ret = -1;
> +
> +	if (!ffa_bus_ops_get())
> +		return -EINVAL;
> +
> +	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
> +
> +	ret = ffa_bus_ops_get()->sync_send_receive(mm_sp_id, &msg);
> +	if (ret != 0)
> +		return ret;
> +
> +	sp_event_ret = msg.data0; /* x3 */
> +
> +	if (sp_event_ret == MM_SUCCESS)
> +		return 0;
> +
> +	/*
> +	 * Failure to notify the MM SP
> +	 */
> +
> +	return -EACCES;
> +}
>  
>  /**
> - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
> + * ffa_discover_mm_sp_id() - Query the MM partition ID
> + *
> + * Use the FF-A driver to get the MM partition ID.
> + * If multiple partitions are found, use the first one.
> + * This is a boot time function.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_discover_mm_sp_id(void)
> +{
> +	u32 count = 0, size = 0;
> +	int ret;
> +	struct ffa_partition_info *parts_info;
> +
> +	if (!ffa_bus_ops_get())
> +		return -EINVAL;
> +
> +	/*
> +	 * get from the driver the count of the SPs matching the UUID
> +	 */
> +	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &count, NULL);
> +	if (ret != 0) {
> +		log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
> +		return ret;
> +	}
> +
> +	if (!count) {
> +		log_info("EFI: No MM partition found\n");
> +		return ret;
> +	}
> +
> +	/*
> +	 * pre-allocate a buffer to be filled by the driver
> +	 * with	 ffa_partition_info structs
> +	 */
> +
> +	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
> +
> +	parts_info = calloc(count, sizeof(struct ffa_partition_info));
> +	if (!parts_info)
> +		return -EINVAL;

-ENOMEM here is more accurate

> +
> +	size = count * sizeof(struct ffa_partition_info);
> +
> +	/*
> +	 * ask the driver to fill the
> +	 * buffer with the SPs info
> +	 */
> +	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &size, parts_info);
> +	if (ret != 0) {
> +		log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret);
> +		free(parts_info);
> +		return ret;
> +	}
> +
> +	/*
> +	 * MM SPs found , use the first one
> +	 */
> +
> +	mm_sp_id = parts_info[0].id;
> +
> +	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
> +
> +	free(parts_info);
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
> + * @comm_buf:		locally allocated communication buffer used for rx/tx
> + * @dsize:				communication buffer size
> + *
> + * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
> + * that there is data to read from the shared buffer.
> + * Communication with the MM SP is performed using FF-A transport.
> + * On the event, MM SP can read the data from the buffer and
> + * update the MM shared buffer with response data.
> + * The response data is copied back to the communication buffer.
> + *
> + * Return:
> + *
> + * EFI status code
> + */
> +static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
> +{
> +	ulong tx_data_size;
> +	int ffa_ret;
> +	struct efi_mm_communicate_header *mm_hdr;
> +	void *virt_shared_buf;
> +
> +	if (!comm_buf)
> +		return EFI_INVALID_PARAMETER;
> +
> +	/* Discover MM partition ID at boot time */
> +	if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
> +		log_err("EFI: Failure to discover MM partition ID at boot time\n");
> +		return EFI_UNSUPPORTED;
> +	}
> +
> +	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> +	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
> +
> +	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
> +		return EFI_INVALID_PARAMETER;
> +
> +	/* Copy the data to the shared buffer */
> +
> +	virt_shared_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
> +	memcpy(virt_shared_buf, comm_buf, tx_data_size);
> +
> +	/*
> +	 * The secure world might have cache disabled for
> +	 * the device region used for shared buffer (which is the case for Optee).
> +	 * In this case, the secure world reads the data from DRAM.
> +	 * Let's flush the cache so the DRAM is updated with the latest data.
> +	 */
> +	#ifdef CONFIG_ARM64
> +	invalidate_dcache_all();

Is this only for arm64?

> +	#endif
> +
> +	/* Announce there is data in the shared buffer */
> +
> +	ffa_ret = ffa_notify_mm_sp();
> +	if (ffa_ret)
> +		unmap_sysmem(virt_shared_buf);

This is a bit confusing handled in different places, can't we just move the
check at the end of the switch cases and remote unmap_sysmem() from case 0?

> +
> +	switch (ffa_ret) {
> +	case 0:
> +	{
> +		ulong rx_data_size;
> +		/* Copy the MM SP response from the shared buffer to the communication buffer */
> +		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> +			sizeof(efi_guid_t) +
> +			sizeof(size_t);
> +
> +		if (rx_data_size > comm_buf_size) {
> +			unmap_sysmem(virt_shared_buf);
> +			return EFI_OUT_OF_RESOURCES;
> +		}
> +
> +		memcpy(comm_buf, virt_shared_buf, rx_data_size);
> +		unmap_sysmem(virt_shared_buf);
> +
> +		return EFI_SUCCESS;
> +	}
> +	case -EINVAL:
> +		return EFI_DEVICE_ERROR;
> +	case -EPERM:
> +		return EFI_INVALID_PARAMETER;
> +	case -EACCES:
> +		return EFI_ACCESS_DENIED;
> +	case -EBUSY:
> +		return EFI_OUT_OF_RESOURCES;
> +	default:
> +		return EFI_ACCESS_DENIED;
> +	}
> +}
> +#endif
> +
> +/**
> + * mm_communicate() - Adjust the communication buffer to the MM SP and send
>   * it to OP-TEE
>   *
> - * @comm_buf:		locally allocted communcation buffer
> + * @comm_buf:		locally allocated communication buffer
>   * @dsize:		buffer size
> + *
> + * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
> + * The comm_buf format is the same for both partitions.
> + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> + * When using the u-boot FF-A  driver, any MM SP is supported.
> + *
>   * Return:		status code
>   */
>  static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> @@ -162,7 +406,12 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
>  	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
>  
> -	ret = optee_mm_communicate(comm_buf, dsize);
> +	ret = ffa_bus_discover();
> +	if (ret != 0)
> +		ret = optee_mm_communicate(comm_buf, dsize);
> +	else
> +		ret = ffa_mm_communicate(comm_buf, dsize);
> +
>  	if (ret != EFI_SUCCESS) {
>  		log_err("%s failed!\n", __func__);
>  		return ret;
> @@ -258,6 +507,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
>  		goto out;
>  	}
>  	*size = var_payload->size;
> +
> +	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
> +			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
> +				MM_VARIABLE_COMMUNICATE_SIZE;
> +	#endif
> +
>  	/*
>  	 * There seems to be a bug in EDK2 miscalculating the boundaries and
>  	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> @@ -697,7 +953,7 @@ void efi_variables_boot_exit_notify(void)
>  		ret = EFI_NOT_FOUND;
>  
>  	if (ret != EFI_SUCCESS)
> -		log_err("Unable to notify StMM for ExitBootServices\n");
> +		log_err("Unable to notify the MM partition for ExitBootServices\n");
>  	free(comm_buf);
>  
>  	/*
> -- 
> 2.17.1
> 

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2022-10-13 10:38                                     ` [PATCH v6 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2022-10-24 14:19                                       ` Jens Wiklander
  2022-11-08 11:13                                         ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Jens Wiklander @ 2022-10-24 14:19 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, ilias.apalodimas, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong, Drew.Reed

On Thu, Oct 13, 2022 at 11:38:48AM +0100, Abdellatif El Khlifi wrote:
> add support for x0-x17 registers used by the SMC calls
> 
> In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
> Results are returned in x0-x17.
> 
> This work is inspired from the following kernel commit:
> 
> arm64: smccc: Add support for SMCCCv1.2 extended input/output registers
> 
> [1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
> 
> 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>
> 
> ---
> 
> Changelog:
> ===============
> 
> v4:
> 
> * rename the commit title and improve description
>   new commit title: the current
> 
> v3:
> 
> * port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
>   commit title:
>       arm64: smccc: add Xn registers support used by SMC calls
> 
> arch/arm/cpu/armv8/smccc-call.S | 53 +++++++++++++++++++++++++++++++++
>  arch/arm/lib/asm-offsets.c      | 14 +++++++++
>  include/linux/arm-smccc.h       | 43 ++++++++++++++++++++++++++
>  3 files changed, 110 insertions(+)
> 
> diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
> index dc92b28777..ec6f299bc9 100644
> --- a/arch/arm/cpu/armv8/smccc-call.S
> +++ b/arch/arm/cpu/armv8/smccc-call.S
> @@ -1,6 +1,8 @@
>  /* SPDX-License-Identifier: GPL-2.0 */
>  /*
>   * Copyright (c) 2015, Linaro Limited
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  #include <linux/linkage.h>
>  #include <linux/arm-smccc.h>
> @@ -45,3 +47,54 @@ ENDPROC(__arm_smccc_smc)
>  ENTRY(__arm_smccc_hvc)
>  	SMCCC	hvc
>  ENDPROC(__arm_smccc_hvc)
> +
> +#ifdef CONFIG_ARM64
> +
> +	.macro SMCCC_1_2 instr
> +	/* Save `res` and free a GPR that won't be clobbered */
> +	stp     x1, x19, [sp, #-16]!
> +
> +	/* Ensure `args` won't be clobbered while loading regs in next step */
> +	mov	x19, x0
> +
> +	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
> +	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
> +	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
> +	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
> +	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
> +	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
> +	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
> +	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
> +	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
> +	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
> +
> +	\instr #0
> +
> +	/* Load the `res` from the stack */
> +	ldr	x19, [sp]
> +
> +	/* Store the registers x0 - x17 into the result structure */
> +	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
> +	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
> +	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
> +	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
> +	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
> +	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
> +	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
> +	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
> +	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
> +
> +	/* Restore original x19 */
> +	ldp     xzr, x19, [sp], #16
> +	ret
> +	.endm
> +
> +/*
> + * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
> + *			  struct arm_smccc_1_2_regs *res);
> + */
> +ENTRY(arm_smccc_1_2_smc)
> +	SMCCC_1_2 smc
> +ENDPROC(arm_smccc_1_2_smc)
> +
> +#endif
> diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
> index 22fd541f9a..1bc2d90faa 100644
> --- a/arch/arm/lib/asm-offsets.c
> +++ b/arch/arm/lib/asm-offsets.c
> @@ -9,6 +9,9 @@
>   * generate asm statements containing #defines,
>   * compile this file to assembler, and then extract the
>   * #defines from the assembly-language output.
> + *
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #include <common.h>
> @@ -117,6 +120,17 @@ int main(void)
>  	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
>  	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
>  	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
> +	#ifdef CONFIG_ARM64
> +		DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
> +		DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
> +		DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
> +		DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
> +		DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
> +		DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
> +		DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
> +		DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
> +		DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
> +	#endif

We don't need another level of indentation here, please follow the
established style in this file.

With that fixed please add
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>

Cheers,
Jens

>  #endif
>  
>  	return 0;
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index e1d09884a1..9105031d55 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -1,6 +1,8 @@
>  /* SPDX-License-Identifier: GPL-2.0 */
>  /*
>   * Copyright (c) 2015, Linaro Limited
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  #ifndef __LINUX_ARM_SMCCC_H
>  #define __LINUX_ARM_SMCCC_H
> @@ -70,6 +72,47 @@ struct arm_smccc_res {
>  	unsigned long a3;
>  };
>  
> +#ifdef CONFIG_ARM64
> +/**
> + * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
> + * @a0-a17 argument values from registers 0 to 17
> + */
> +struct arm_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;
> +};
> +
> +/**
> + * arm_smccc_1_2_smc() - make SMC calls
> + * @args: arguments passed via struct arm_smccc_1_2_regs
> + * @res: result values via struct arm_smccc_1_2_regs
> + *
> + * This function is used to make SMC calls following SMC Calling Convention
> + * v1.2 or above. The content of the supplied param are copied from the
> + * structure to registers prior to the SMC instruction. The return values
> + * are updated with the content from registers on return from the SMC
> + * instruction.
> + */
> +asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
> +				  struct arm_smccc_1_2_regs *res);
> +#endif
> +
>  /**
>   * struct arm_smccc_quirk - Contains quirk information
>   * @id: quirk identification
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-10-13 10:38                                     ` [PATCH v6 03/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
@ 2022-10-25  9:31                                       ` Jens Wiklander
  2022-10-25 10:27                                         ` Abdellatif El Khlifi
  2022-11-08 11:28                                         ` Abdellatif El Khlifi
  0 siblings, 2 replies; 478+ messages in thread
From: Jens Wiklander @ 2022-10-25  9:31 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, ilias.apalodimas, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong, Drew.Reed

On Thu, Oct 13, 2022 at 11:38:50AM +0100, Abdellatif El Khlifi wrote:
> Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0
> 
> The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World leveraging TrustZone
> technology.
> 
> This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> querying the FF-A framework from the secure world.
> 
> 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> 
> In u-boot FF-A design, FF-A is considered as a discoverable bus.

U-Boot

> The Secure World is considered as one entity to communicate with
> using the FF-A bus. FF-A communication is handled by one device and
> one instance (the bus). This FF-A driver takes care of all the
> interactions between Normal world and Secure World.
> 
> The driver exports its operations to be used by upper layers.
> 
> Exported operations:
> 
> - partition_info_get
> - sync_send_receive
> - rxtx_unmap
> 
> [1]: https://developer.arm.com/documentation/den0077/latest/
> 
> 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>
> 
> ---
> 
> Changelog:
> ===============
> 
> v6:
> 
> * drop use of EFI runtime support (We decided with Linaro to add this later)
> * drop discovery from initcalls (discovery will be on demand by FF-A users)
> * set the alignment of the RX/TX buffers to the larger translation granule size
> * move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
> * update the documentation and move it to doc/arch/arm64.ffa.rst
> 
> v4:
> 
> * add doc/README.ffa.drv
> * moving the FF-A driver work to drivers/firmware/arm-ffa
> * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
>   #if defined by #if CONFIG_IS_ENABLED
> * improving error handling by mapping the FF-A errors to standard errors
>   and logs
> * replacing panics with an error log and returning an error code
> * improving features discovery in FFA_FEATURES by introducing
>   rxtx_min_pages private data field
> * add ffa_remove and ffa_unbind functions
> * improve how the driver behaves when bus discovery is done more than
>   once
> 
> v3:
> 
> * align the interfaces of the u-boot FF-A driver with those in the linux
>   FF-A driver
> * remove the FF-A helper layer
> * make the u-boot FF-A driver independent from EFI
> * provide an optional config that enables copying the driver data to EFI
>   runtime section at ExitBootServices service
> * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
> 
> v2:
> 
> * make FF-A bus discoverable using device_{bind, probe} APIs
> * remove device tree support
> 
> v1:
> 
> * introduce FF-A bus driver with device tree support
> 
>  MAINTAINERS                               |    7 +
>  doc/arch/arm64.ffa.rst                    |  207 ++++
>  doc/arch/index.rst                        |    1 +
>  drivers/Kconfig                           |    2 +
>  drivers/Makefile                          |    1 +
>  drivers/firmware/arm-ffa/Kconfig          |   30 +
>  drivers/firmware/arm-ffa/Makefile         |    6 +
>  drivers/firmware/arm-ffa/arm-ffa-uclass.c |   16 +
>  drivers/firmware/arm-ffa/arm_ffa_prv.h    |  196 +++
>  drivers/firmware/arm-ffa/core.c           | 1337 +++++++++++++++++++++
>  include/arm_ffa.h                         |   93 ++
>  include/dm/uclass-id.h                    |    4 +
>  12 files changed, 1900 insertions(+)
>  create mode 100644 doc/arch/arm64.ffa.rst
>  create mode 100644 drivers/firmware/arm-ffa/Kconfig
>  create mode 100644 drivers/firmware/arm-ffa/Makefile
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
>  create mode 100644 drivers/firmware/arm-ffa/core.c
>  create mode 100644 include/arm_ffa.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a26b36c7c2..496f47a516 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -248,6 +248,13 @@ F:	drivers/net/cortina_ni.h
>  F:	drivers/net/phy/ca_phy.c
>  F:	configs/cortina_presidio-asic-pnand_defconfig
>  
> +ARM FF-A
> +M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +S:	Maintained
> +F:	doc/arch/arm64.ffa.rst
> +F:	drivers/firmware/arm-ffa/
> +F:	include/arm_ffa.h
> +
>  ARM FREESCALE IMX
>  M:	Stefano Babic <sbabic@denx.de>
>  M:	Fabio Estevam <festevam@gmail.com>
> diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> new file mode 100644
> index 0000000000..e98d2cf2b3
> --- /dev/null
> +++ b/doc/arch/arm64.ffa.rst
> @@ -0,0 +1,207 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +
> +Arm FF-A Driver
> +===============
> +
> +Summary
> +-------
> +
> +FF-A stands for Firmware Framework for Arm A-profile processors.
> +
> +FF-A specifies interfaces that enable a pair of software sandboxes to
> +communicate with each other. A sandbox aka partition could
> +be a VM in the Normal or Secure world, an application in S-EL0, or a
> +Trusted OS in S-EL1.
> +
> +This FF-A driver implements the interfaces to communicate with partitions in
> +the Secure world aka Secure partitions (SPs).
> +
> +The driver specifically focuses on communicating with SPs that isolate portions
> +of EFI runtime services that must run in a protected environment which is
> +inaccessible by the Host OS or Hypervisor. Examples of such services are
> +set/get variables.
> +
> +FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> +
> +- Discover the presence of SPs of interest
> +- Access an SP's service through communication protocols
> +  e.g. EFI MM communication protocol
> +
> +FF-A and SMC specifications
> +-------------------------------------------
> +
> +The current implementation of the driver relies on FF-A specification v1.0
> +and uses SMC32 calling convention.
> +
> +At this stage we only need the FF-A v1.0 features.
> +
> +The driver has been tested with Optee OS which supports SMC32 for most of

s/Optee OS/OP-TEE/

> +the SMC ABIs.
> +
> +For more details please refer to the FF-A v1.0 spec:
> +https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=
> +
> +Hypervisors are supported if they are configured to trap SMC calls.
> +
> +The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
> +
> +For more details please refer to the SMC Calling Convention v1.2 spec:
> +https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
> +
> +Supported hardware
> +--------------------------------
> +
> +Aarch64 plaforms
> +
> +Configuration
> +----------------------
> +
> +CONFIG_ARM_FFA_TRANSPORT
> +    Enables the FF-A bus driver. Turn this on if you want to use FF-A
> +    communication.
> +
> +CONFIG_SANDBOX_FFA
> +    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
> +    Sandbox and provides functional tests for FF-A.
> +
> +FF-A ABIs under the hood
> +---------------------------------------
> +
> +Invoking an FF-A ABI involves providing to the secure world/hypervisor the
> +expected arguments from the ABI.
> +
> +The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction
> +is executed.
> +
> +At the secure side level or hypervisor the ABI is handled at a higher exception
> +level and the arguments are read and processed.
> +
> +The response is put back through x0 to x7 registers and control is given back
> +to the U-boot FF-A driver (non-secure world).
> +
> +The driver reads the response and processes it accordingly.
> +
> +This methodology applies to all the FF-A ABIs in the driver.
> +
> +FF-A bus discovery in U-boot

U-Boot, please search and replace.

> +-------------------------------------------
> +
> +When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is discovered on
> +demand by the clients (users).
> +
> +Clients can discover the FF-A bus using ffa_bus_discover() API which triggers the
> +discovery process.
> +
> +ffa_bus_discover() creates, binds and probes the arm_ffa device using
> +device_{bind, probe} APIs.
> +
> +The discovery process consists in communicating with secure world (or hypervisor)
> +and querying specific data.
> +
> +The discovery process takes place during the arm_ffa device probing which is
> +handled by ffa_probe().
> +
> +The FF-A bus discovery is successful and the bus is ready for use when these
> +operations succeed:
> +
> +- querying the FF-A framework version
> +- querying from secure world the U-boot endpoint ID
> +- querying from secure world the RX/TX mapping  features
> +- mapping the RX/TX buffers
> +- querying from secure world all the partitions information
> +
> +Discovery failure results in a probing failure and the arm_ffa device is
> +destroyed.
> +
> +Requirements for clients
> +-------------------------------------
> +
> +When using the FF-A bus with EFI, clients must:
> +
> +- Query SPs in EFI boot time mode using the service UUID.
> +- Unmap RX/TX buffers before EFI runtime mode starts.
> +
> +The RX/TX buffers are only available at EFI boot time. Querying partitions is
> +done at boot time and data is cached for future use.
> +
> +RX/TX buffers should be unmapped by the user before EFI runtime mode
> +starts. The driver provides a bus operation for that: rxtx_unmap()
> +
> +If  RX/TX buffers created by U-boot are not unmapped and by
> +consequence becoming available at EFI runtime, secure world will get confused
> +about RX/TX buffers ownership (U-boot vs kernel).
> +
> +The bus driver layer
> +------------------------------
> +
> +The driver comes on top of the SMCCC layer and is implemented in
> +drivers/firmware/arm-ffa/core.c
> +
> +The driver provides the following features:
> +
> +- Support for the 32-bit version of the following ABIs:
> +
> +FFA_VERSION
> +FFA_ID_GET
> +FFA_FEATURES
> +FFA_PARTITION_INFO_GET
> +FFA_RXTX_UNMAP
> +FFA_RX_RELEASE
> +FFA_RUN
> +FFA_ERROR
> +FFA_SUCCESS
> +FFA_INTERRUPT
> +
> +- Support for the 64-bit version of the following ABIs:
> +
> +FFA_RXTX_MAP
> +FFA_MSG_SEND_DIRECT_REQ
> +FFA_MSG_SEND_DIRECT_RESP
> +
> +- Processing the received data from the secure world/hypervisor and caching it
> +
> +- Hiding from upper layers the FF-A protocol and registers details. Upper
> +  layers focus on exchanged data, the driver takes care of how to transport
> +  that to the secure world/hypervisor using FF-A
> +
> +- The driver provides callbacks to be used by clients to access the FF-A bus:
> +
> +partition_info_get
> +sync_send_receive
> +rxtx_unmap
> +
> +- FF-A bus discovery makes sure FF-A framework is responsive and compatible
> +  with the driver
> +
> +- FF-A bus can be compiled and used without EFI
> +
> +Using armffa command
> +-----------------------------------
> +
> +armffa is a command showcasing how to use the FF-A driver and how to invoke
> +its operations.
> +
> +This provides a guidance to the client developers on how to call the FF-A bus
> +interfaces.
> +
> +Usage:
> +
> +armffa <sub-command> <arguments>
> +
> +sub-commands:
> +
> +        getpart <partition UUID>
> +
> +            lists the partition(s) info
> +
> +        ping <partition ID>
> +
> +            sends a data pattern to the specified partition

It may be worth mentioning that this is an implementation defined
command.

> +
> +        devlist
> +
> +            displays the arm_ffa device info
> +
> +Contributors
> +------------
> +   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> diff --git a/doc/arch/index.rst b/doc/arch/index.rst
> index 792d9182c3..8d1ab0ad4e 100644
> --- a/doc/arch/index.rst
> +++ b/doc/arch/index.rst
> @@ -8,6 +8,7 @@ Architecture-specific doc
>  
>     arc
>     arm64
> +   arm64.ffa
>     m68k
>     mips
>     nios2
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index 8b6fead351..b06b1ae481 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
>  
>  source "drivers/adc/Kconfig"
>  
> +source "drivers/firmware/arm-ffa/Kconfig"
> +
>  source "drivers/ata/Kconfig"
>  
>  source "drivers/axi/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 9d9f69a3c9..bf8d7b8cfc 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -111,6 +111,7 @@ obj-y += iommu/
>  obj-y += smem/
>  obj-y += thermal/
>  obj-$(CONFIG_TEE) += tee/
> +obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
>  obj-y += axi/
>  obj-y += ufs/
>  obj-$(CONFIG_W1) += w1/
> diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> new file mode 100644
> index 0000000000..f1427535f9
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/Kconfig
> @@ -0,0 +1,30 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +config ARM_FFA_TRANSPORT
> +	bool "Enable Arm Firmware Framework for Armv8-A driver"
> +	depends on DM && ARM64
> +	select ARM_SMCCC
> +	select LIB_UUID
> +	select DEVRES
> +	help
> +	  The Firmware Framework for Arm A-profile processors (FF-A)
> +	  describes interfaces (ABIs) that standardize communication
> +	  between the Secure World and Normal World leveraging TrustZone
> +	  technology.
> +
> +	  This driver is based on FF-A specification v1.0 and uses SMC32
> +	  calling convention.
> +
> +	  FF-A specification:
> +
> +	  https://developer.arm.com/documentation/den0077/a/?lang=en
> +
> +	  In u-boot FF-A design, FF-A is considered as a discoverable bus.

U-Boot

> +	  The Secure World is considered as one entity to communicate with
> +	  using the FF-A bus.
> +	  FF-A communication is handled by one device and one instance (the bus).
> +	  This FF-A driver takes care of all the interactions between Normal world
> +	  and Secure World.
> +
> +	  For more details about the FF-A driver, please refer to doc/README.ffa.drv

Not doc/arch/arm64.ffa.rst?

> +
> diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
> new file mode 100644
> index 0000000000..043a8915be
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# (C) Copyright 2022
> +# Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com.
> +
> +obj-y += arm-ffa-uclass.o core.o
> diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> new file mode 100644
> index 0000000000..7d9695d289
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> @@ -0,0 +1,16 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <asm/global_data.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +UCLASS_DRIVER(ffa) = {
> +	.name		= "ffa",
> +	.id		= UCLASS_FFA,
> +};
> diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> new file mode 100644
> index 0000000000..7bc90f7f66
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> @@ -0,0 +1,196 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#ifndef __ARM_FFA_PRV_H
> +#define __ARM_FFA_PRV_H
> +
> +#include <arm_ffa.h>
> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
> +#include <linux/arm-smccc.h>
> +
> +/*
> + * This header is private. It is exclusively used by the FF-A driver
> + */
> +
> +/* FF-A core driver name */
> +#define FFA_DRV_NAME "arm_ffa"
> +
> +/* FF-A driver version definitions */
> +
> +#define MAJOR_VERSION_MASK		GENMASK(30, 16)
> +#define MINOR_VERSION_MASK		GENMASK(15, 0)
> +#define GET_FFA_MAJOR_VERSION(x)		\
> +				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> +#define GET_FFA_MINOR_VERSION(x)		\
> +				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> +#define PACK_VERSION_INFO(major, minor)			\
> +	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
> +	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> +
> +#define FFA_MAJOR_VERSION		(1)
> +#define FFA_MINOR_VERSION		(0)
> +#define FFA_VERSION_1_0		\
> +			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> +
> +/* Endpoint ID mask (u-boot endpoint ID) */
> +
> +#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
> +#define GET_SELF_ENDPOINT_ID(x)		\
> +			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> +
> +#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
> +#define PREP_SELF_ENDPOINT_ID(x)		\
> +			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> +
> +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> +
> +#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
> +#define PREP_PART_ENDPOINT_ID(x)		\
> +			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> +
> +/*
> + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> + */
> +
> +#define FFA_SMC(calling_convention, func_num)				\
> +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
> +			   ARM_SMCCC_OWNER_STANDARD, (func_num))
> +
> +#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> +#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
> +
> +enum ffa_abis {
> +	FFA_ERROR					= 0x60,
> +	FFA_SUCCESS					= 0x61,
> +	FFA_INTERRUPT				= 0x62,
> +	FFA_VERSION					= 0x63,
> +	FFA_FEATURES				= 0x64,
> +	FFA_RX_RELEASE				= 0x65,
> +	FFA_RXTX_MAP				= 0x66,
> +	FFA_RXTX_UNMAP			= 0x67,
> +	FFA_PARTITION_INFO_GET		= 0x68,
> +	FFA_ID_GET					= 0x69,
> +	FFA_RUN						= 0x6D,
> +	FFA_MSG_SEND_DIRECT_REQ	= 0x6F,
> +	FFA_MSG_SEND_DIRECT_RESP	= 0x70,
> +
> +	/* to be updated when adding new FFA IDs */
> +	FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
> +	FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
> +};
> +
> +/* number of the errors supported by the FF-A specification */
> +#define MAX_NUMBER_FFA_ERR 9
> +
> +/* container structure and helper macros to map between an FF-A error and relevant error log */
> +struct ffa_abi_errmap {
> +	char *err_str[MAX_NUMBER_FFA_ERR];
> +};
> +
> +#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
> + *
> + */
> +struct ffa_partition_uuid {
> +	u32 a1; /* w1 */
> +	u32 a2; /* w2 */
> +	u32 a3; /* w3 */
> +	u32 a4; /* w4 */
> +};
> +
> +/**
> + * enum ffa_rxtx_buf_sizes - minimum sizes supported
> + * for the RX/TX buffers
> + */
> +enum ffa_rxtx_buf_sizes {
> +	RXTX_4K,
> +	RXTX_64K,
> +	RXTX_16K
> +};
> +
> +/**
> + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> + * @rxbuf:	virtual address of the RX buffer
> + * @txbuf:	virtual address of the TX buffer
> + * @rxtx_min_pages:	RX/TX buffers minimum size in pages
> + *
> + * Data structure hosting the virtual addresses of the mapped RX/TX buffers
> + * These addresses are used by the FF-A functions that use the RX/TX buffers
> + */
> +struct ffa_rxtxpair {
> +	u64 rxbuf; /* virtual address */
> +	u64 txbuf; /* virtual address */
> +	size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
> +};
> +
> +/**
> + * struct ffa_partition_desc - the secure partition descriptor
> + * @info:	partition information
> + * @sp_uuid:	the secure partition UUID
> + *
> + * Each partition has its descriptor containing the partitions information and the UUID
> + */
> +struct ffa_partition_desc {
> +	struct ffa_partition_info info;
> +	struct ffa_partition_uuid sp_uuid;
> +};
> +
> +/**
> + * struct ffa_partitions - descriptors for all secure partitions
> + * @count:	The number of partitions descriptors
> + * @descs	The partitions descriptors table
> + *
> + * This data structure contains the partitions descriptors table
> + */
> +struct ffa_partitions {
> +	u32 count;
> +	struct ffa_partition_desc *descs; /* virtual address */
> +};
> +
> +/**
> + * struct ffa_prvdata - the driver private data structure
> + *
> + * @dev:	The arm_ffa device under u-boot driver model
> + * @ffa_ops:	The driver operations structure
> + * @fwk_version:	FF-A framework version
> + * @id:	u-boot endpoint ID
> + * @partitions:	The partitions descriptors structure
> + * @pair:	The RX/TX buffers pair
> + * @invoke_ffa_fn:	The function executing the FF-A function
> + *
> + * The driver data structure hosting all resident data.
> + */
> +struct ffa_prvdata {
> +	struct udevice *dev;
> +	struct ffa_bus_ops ffa_ops;
> +	u32 fwk_version;
> +	u16 id;
> +	struct ffa_partitions partitions;
> +	struct ffa_rxtxpair pair;
> +	invoke_ffa_fn_t invoke_ffa_fn;
> +};
> +
> +/**
> + * ffa_device_get - create, bind and probe the arm_ffa device
> + */
> +int ffa_device_get(void);
> +
> +/**
> + * ffa_bus_prvdata_get - bus driver private data getter
> + */
> +struct ffa_prvdata **ffa_bus_prvdata_get(void);
> +
> +#endif
> diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
> new file mode 100644
> index 0000000000..324367d12b
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/core.c
> @@ -0,0 +1,1337 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include "arm_ffa_prv.h"
> +#include <asm/global_data.h>
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/device-internal.h>
> +#include <dm/devres.h>
> +#include <dm/root.h>
> +#include <linux/errno.h>
> +#include <linux/sizes.h>
> +#include <log.h>
> +#include <malloc.h>
> +#include <string.h>
> +#include <uuid.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/**
> + * The device private data structure containing all the
> + * data read from secure world
> + */
> +struct ffa_prvdata *ffa_priv_data;
> +
> +/* Error mapping declarations */
> +
> +int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
> +	0,
> +	-EOPNOTSUPP,	/* NOT_SUPPORTED */
> +	-EINVAL,	/* INVALID_PARAMETERS */
> +	-ENOMEM,	/* NO_MEMORY */
> +	-EBUSY,		/* BUSY */
> +	-EINTR,		/* INTERRUPTED */
> +	-EACCES,	/* DENIED */
> +	-EAGAIN,	/* RETRY */
> +	-ECANCELED,	/* ABORTED */
> +};
> +
> +struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
> +	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
> +		{
> +			"",

Shouldn't all these empty strings be NULL instead? Given that's that
what you check for in ffa_print_error_log() below.

You could save a few lines by using designated initializers for only the
used elements in err_str for each FF-A function ID.

> +			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
> +			"", /* INVALID_PARAMETERS */
> +			"", /* NO_MEMORY */
> +			"", /* BUSY */
> +			"", /* INTERRUPTED */
> +			"", /* DENIED */
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
> +		{
> +			"",
> +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> +			"", /* INVALID_PARAMETERS */
> +			"", /* NO_MEMORY */
> +			"", /* BUSY */
> +			"", /* INTERRUPTED */
> +			"", /* DENIED */
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
> +		{
> +			"",
> +			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
> +			"", /* INVALID_PARAMETERS */
> +			"", /* NO_MEMORY */
> +			"", /* BUSY */
> +			"", /* INTERRUPTED */
> +			"", /* DENIED */
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
> +		{
> +			"",
> +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> +			"INVALID_PARAMETERS: Unrecognized UUID",
> +			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
> +			"BUSY: RX buffer of the caller is not free",
> +			"", /* INTERRUPTED */
> +			"DENIED: Callee is not in a state to handle this request",
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
> +			{
> +			"",
> +			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
> +			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
> +			"", /* NO_MEMORY */
> +			"", /* BUSY */
> +			"", /* INTERRUPTED */
> +			"", /* DENIED */
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
> +			{
> +			"",
> +			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
> +			"", /* INVALID_PARAMETERS */
> +			"", /* NO_MEMORY */
> +			"", /* BUSY */
> +			"", /* INTERRUPTED */
> +			"DENIED: Caller did not have ownership of the RX buffer",
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
> +			{
> +			"",
> +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> +			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
> +			"NO_MEMORY: Not enough memory",
> +			"", /* BUSY */
> +			"", /* INTERRUPTED */
> +			"DENIED: Buffer pair already registered",
> +			"", /* RETRY */
> +			"", /* ABORTED */
> +		},
> +	},
> +};
> +
> +/**
> + * ffa_to_std_errno - convert FF-A error code to standard error code
> + * @ffa_errno:	Error code returned by the FF-A ABI
> + *
> + * This function maps the given FF-A error code as specified
> + * by the spec to a u-boot standard error code.
> + *
> + * Return:
> + *
> + * The standard error code on success. . Otherwise, failure
> + */
> +int ffa_to_std_errno(int ffa_errno)
> +{
> +	int err_idx = -ffa_errno;
> +
> +	/* map the FF-A error code to the standard u-boot error code */
> +	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
> +		return ffa_to_std_errmap[err_idx];
> +	return -EINVAL;
> +}
> +
> +/**
> + * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
> + * @ffa_id:	FF-A ABI ID
> + * @ffa_errno:	Error code returned by the FF-A ABI
> + *
> + * This function maps the FF-A error code to the error log relevant to the
> + * selected FF-A ABI. Then the error log is printed.
> + *
> + * Return:
> + *
> + * 0 on success. . Otherwise, failure
> + */
> +int ffa_print_error_log(u32 ffa_id, int ffa_errno)
> +{
> +	int err_idx = -ffa_errno, abi_idx = 0;
> +
> +	/* map the FF-A error code to the corresponding error log */
> +
> +	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
> +		return -EINVAL;
> +
> +	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
> +		return -EINVAL;
> +
> +	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
> +	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
> +		return -EINVAL;
> +
> +	if (!err_msg_map[abi_idx].err_str || !err_msg_map[abi_idx].err_str[err_idx])

err_str can't be NULL since it's an array in the struct ffa_abi_errmap.

> +		return -EINVAL;
> +
> +	ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
> +
> +	return 0;
> +}
> +
> +/*
> + * Driver core functions
> + */
> +
> +/**
> + * ffa_remove_device - removes the arm_ffa device
> + * @dev:	the device to be removed
> + *
> + * This function makes sure the arm_ffa device is removed
> + * No need to free the kmalloced data when the device is destroyed.
> + * It's automatically done by devm management by
> + * device_remove() -> device_free() -> devres_release_probe().
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_remove_device(struct udevice *dev)
> +{
> +	int ret;
> +
> +	if (!dev) {
> +		ffa_err("no udevice found");
> +		return -ENODEV;
> +	}
> +
> +	ret = device_remove(dev, DM_REMOVE_NORMAL);
> +	if (ret) {
> +		ffa_err("unable to remove. err:%d\n", ret);
> +		return ret;
> +	}
> +
> +	ffa_info("device removed and freed");
> +
> +	ret = device_unbind(dev);
> +	if (ret) {
> +		ffa_err("unable to unbind. err:%d\n", ret);
> +		return ret;
> +	}
> +
> +	ffa_info("device unbound");
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_device_get - create, bind and probe the arm_ffa device
> + *
> + * This function makes sure the arm_ffa device is
> + * created, bound to this driver, probed and ready to use.
> + * Arm FF-A transport is implemented through a single u-boot
> + * device managing the FF-A bus (arm_ffa).
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_device_get(void)
> +{
> +	int ret;
> +	struct udevice *dev = NULL;
> +
> +	ret = device_bind(dm_root(),
> +			  DM_DRIVER_GET(arm_ffa),
> +			  FFA_DRV_NAME,
> +			  NULL,
> +			  ofnode_null(),
> +			  &dev);

There's no need for separate lines for each argument, please fold up a bit.

> +	if (ret)
> +		return ret;
> +
> +	/* The FF-A bus discovery succeeds when probing is successful */
> +	ret = device_probe(dev);
> +	if (ret) {
> +		ffa_err("arm_ffa device probing failed");
> +		ffa_remove_device(dev);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_get_version - FFA_VERSION handler function
> + *
> + * This function implements FFA_VERSION FF-A function
> + * to get from the secure world the FF-A framework version
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_get_version(void)
> +{
> +	u16 major, minor;
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_VERSION),
> +			.a1 = FFA_VERSION_1_0

It's generally preferred to have comma after the last initializer too.

It could also be worth comparing with the style (alignment and folding
up where possible) of the corresponding driver in the Linux kernel which
I find a bit easier to read. However, checkpatch seems happy enough so I
guess it's not a big deal.

I asked earlier why you're not supporting the latest version, 1.1, but
you never answered that.

> +			}, &res);
> +
> +	ffa_errno = res.a0;
> +	if (ffa_errno < 0) {
> +		ffa_print_error_log(FFA_VERSION, ffa_errno);
> +		return ffa_to_std_errno(ffa_errno);
> +	}
> +
> +	major = GET_FFA_MAJOR_VERSION(res.a0);
> +	minor = GET_FFA_MINOR_VERSION(res.a0);
> +
> +	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> +		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> +
> +	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
> +		ffa_info("Versions are compatible ");
> +
> +		ffa_priv_data->fwk_version = res.a0;
> +
> +		return 0;
> +	}
> +
> +	ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
> +		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> +
> +	return -EPROTONOSUPPORT;
> +}
> +
> +/**
> + * ffa_get_endpoint_id - FFA_ID_GET handler function
> + *
> + * This function implements FFA_ID_GET FF-A function
> + * to get from the secure world u-boot endpoint ID
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_get_endpoint_id(void)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_ID_GET)
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
> +		ffa_info("endpoint ID is %u", ffa_priv_data->id);
> +
> +		return 0;
> +	}
> +
> +	ffa_errno = res.a2;
> +
> +	ffa_print_error_log(FFA_ID_GET, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
> + * @prop_field: properties field obtained from FFA_FEATURES ABI
> + *
> + * This function sets the minimum number of pages
> + *  in each of the RX/TX buffers in the private data structure
> + *
> + * Return:
> + *
> + * buf_4k_pages points to the returned number of pages
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
> +{
> +	if (!ffa_priv_data)
> +		return -EINVAL;
> +
> +	switch (prop_field) {
> +	case RXTX_4K:
> +		ffa_priv_data->pair.rxtx_min_pages = 1;
> +		break;
> +	case RXTX_16K:
> +		ffa_priv_data->pair.rxtx_min_pages = 4;
> +		break;
> +	case RXTX_64K:
> +		ffa_priv_data->pair.rxtx_min_pages = 16;
> +		break;
> +	default:
> +		ffa_err("RX/TX buffer size not supported");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
> + *
> + * This function implements FFA_FEATURES FF-A function
> + * to retrieve the FFA_RXTX_MAP features
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_get_rxtx_map_features(void)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_FEATURES),
> +			.a1 = FFA_SMC_64(FFA_RXTX_MAP)
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> +		return ffa_set_rxtx_buffers_pages_cnt((u32)res.a2);

The cast isn't needed.

> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_FEATURES, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> + *
> + * This  function  frees the RX/TX buffers
> + *
> + */
> +static void ffa_free_rxtx_buffers(void)
> +{
> +	ffa_info("Freeing RX/TX buffers");
> +
> +	if (ffa_priv_data->pair.rxbuf) {
> +		free((void *)ffa_priv_data->pair.rxbuf);
> +		ffa_priv_data->pair.rxbuf = 0;
> +	}
> +
> +	if (ffa_priv_data->pair.txbuf) {
> +		free((void *)ffa_priv_data->pair.txbuf);
> +		ffa_priv_data->pair.txbuf = 0;
> +	}
> +}
> +
> +/**
> + * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
> + *
> + * This function is used by ffa_map_rxtx_buffers to allocate
> + * the RX/TX buffers before mapping them. The allocated memory is physically
> + * contiguous since memalign ends up calling malloc which allocates
> + * contiguous memory in u-boot.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_alloc_rxtx_buffers(void)
> +{
> +	u64 bytes;
> +
> +	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
> +		 ffa_priv_data->pair.rxtx_min_pages);
> +
> +	bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> +
> +	/*
> +	 * The alignment of the RX and TX buffers must be equal
> +	 * to the larger translation granule size
> +	 */
> +
> +	ffa_priv_data->pair.rxbuf = (u64)memalign(bytes, bytes);
> +	if (!ffa_priv_data->pair.rxbuf) {
> +		ffa_err("failure to allocate RX buffer");
> +		return -ENOBUFS;
> +	}
> +
> +	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
> +
> +	ffa_priv_data->pair.txbuf = (u64)memalign(bytes, bytes);
> +	if (!ffa_priv_data->pair.txbuf) {
> +		free((void *)ffa_priv_data->pair.rxbuf);
> +		ffa_priv_data->pair.rxbuf = 0;
> +		ffa_err("failure to allocate the TX buffer");
> +		return -ENOBUFS;
> +	}
> +
> +	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
> +
> +	/*
> +	 * make sure the buffers are cleared before use
> +	 */
> +	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
> +	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> + *
> + * This function implements FFA_RXTX_MAP FF-A function
> + * to map the RX/TX buffers
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_map_rxtx_buffers(void)
> +{
> +	int ret;
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ret = ffa_alloc_rxtx_buffers();
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * we need to pass the physical addresses of the RX/TX buffers
> +	 * in u-boot physical/virtual mapping is 1:1
> +	 *no need to convert from virtual to physical

A space is missing after the '*'.

> +	 */
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
> +			.a1 = ffa_priv_data->pair.txbuf,
> +			.a2 = ffa_priv_data->pair.rxbuf,
> +			.a3 = ffa_priv_data->pair.rxtx_min_pages,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		ffa_info("RX/TX buffers mapped");
> +		return 0;
> +	}
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
> +
> +	ffa_free_rxtx_buffers();
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
> + *
> + * This function implements FFA_RXTX_UNMAP FF-A function
> + * to unmap the RX/TX buffers
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_unmap_rxtx_buffers(void)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
> +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id)
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		ffa_free_rxtx_buffers();
> +		return 0;
> +	}
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
> + *
> + * This function invokes FFA_RX_RELEASE FF-A function
> + * to release the ownership of the RX buffer
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_release_rx_buffer(void)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_RX_RELEASE)
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> +		return 0;
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_uuid_are_identical - checks whether two given UUIDs are identical
> + * @uuid1: first UUID
> + * @uuid2: second UUID
> + *
> + * This function is used by ffa_read_partitions_info to search
> + * for a UUID in the partitions descriptors table
> + *
> + * Return:
> + *
> + * 1 when UUIDs match. Otherwise, 0
> + */
> +int ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
> +			   const struct ffa_partition_uuid *uuid2)

Would it make sense to use the bool type instead?

> +{
> +	if (!uuid1 || !uuid2)
> +		return 0;
> +
> +	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
> +}
> +
> +/**
> + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> + *							and saves it in the private structure
> + * @count: The number of partitions queried
> + * @part_uuid: Pointer to the partition(s) UUID
> + *
> + * This function reads the partitions information
> + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> + * data structure.
> + *
> + * Return:
> + *
> + * The private data structure is updated with the partition(s) information
> + * 0 is returned on success. Otherwise, failure
> + */
> +static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
> +{
> +	if (!count) {
> +		ffa_err("no partition detected");
> +		return -ENODATA;
> +	}
> +
> +	ffa_info("Reading partitions data from the RX buffer");
> +
> +	if (!part_uuid) {
> +		/*
> +		 * querying information of all partitions
> +		 */
> +		u64 buf_bytes;
> +		u64 data_bytes;
> +		u32 desc_idx;
> +		struct ffa_partition_info *parts_info;
> +
> +		data_bytes = count * sizeof(struct ffa_partition_desc);
> +
> +		buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> +
> +		if (data_bytes > buf_bytes) {
> +			ffa_err("partitions data size exceeds the RX buffer size:");
> +			ffa_err("    sizes in bytes: data %llu , RX buffer %llu ",
> +				data_bytes,
> +				buf_bytes);
> +
> +			return -ENOMEM;
> +		}
> +
> +		ffa_priv_data->partitions.descs = devm_kmalloc(ffa_priv_data->dev, data_bytes,
> +							       __GFP_ZERO);
> +		if (!ffa_priv_data->partitions.descs) {
> +			ffa_err("cannot  allocate partitions data buffer");
> +			return -ENOMEM;
> +		}
> +
> +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> +
> +		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
> +			ffa_priv_data->partitions.descs[desc_idx].info =
> +				parts_info[desc_idx];
> +
> +			ffa_info("Partition ID %x : info cached",
> +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> +		}
> +
> +		ffa_priv_data->partitions.count = count;
> +
> +		ffa_info("%d partition(s) found and cached", count);
> +
> +	} else {
> +		u32 rx_desc_idx, cached_desc_idx;
> +		struct ffa_partition_info *parts_info;
> +		u8 desc_found;
> +
> +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> +
> +		/*
> +		 * search for the SP IDs read from the RX buffer
> +		 * in the already cached SPs.
> +		 * Update the UUID when ID found.
> +		 */
> +		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
> +			desc_found = 0;
> +
> +			/*
> +			 * search the current ID in the cached partitions
> +			 */
> +			for (cached_desc_idx = 0;
> +			     cached_desc_idx < ffa_priv_data->partitions.count;
> +			     cached_desc_idx++) {
> +				/*
> +				 * save the UUID
> +				 */
> +				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
> +				    parts_info[rx_desc_idx].id) {
> +					ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
> +						*part_uuid;
> +
> +					desc_found = 1;
> +					break;
> +				}
> +			}
> +
> +			if (!desc_found)
> +				return -ENODATA;
> +		}
> +	}
> +
> +	return  0;
> +}
> +
> +/**
> + * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
> + *
> + * @part_uuid: Pointer to the partition(s) UUID
> + * @pcount: Pointer to the number of partitions variable filled when querying
> + *
> + * This function executes the FFA_PARTITION_INFO_GET
> + * to query the partitions data. Then, it calls ffa_read_partitions_info
> + * to save the data in the private data structure.
> + *
> + * After reading the data the RX buffer is released using ffa_release_rx_buffer
> + *
> + * Return:
> + *
> + * When part_uuid is NULL, all partitions data are retrieved from secure world
> + * When part_uuid is non NULL, data for partitions matching the given UUID are
> + * retrieved and the number of partitions is returned
> + * 0 is returned on success. Otherwise, failure
> + */
> +static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
> +				     u32 *pcount)
> +{
> +	struct ffa_partition_uuid query_uuid = {0};
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	/*
> +	 * If a UUID is specified. Information for one or more
> +	 * partitions in the system is queried. Otherwise, information
> +	 * for all installed partitions is queried
> +	 */
> +
> +	if (part_uuid) {
> +		if (!pcount)
> +			return -EINVAL;
> +
> +		query_uuid = *part_uuid;
> +	} else if (pcount) {
> +		return -EINVAL;
> +	}
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
> +			.a1 = query_uuid.a1,
> +			.a2 = query_uuid.a2,
> +			.a3 = query_uuid.a3,
> +			.a4 = query_uuid.a4
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		int ret;
> +
> +		/*
> +		 * res.a2 contains the count of partition information descriptors
> +		 * populated in the RX buffer
> +		 */
> +		if (res.a2) {
> +			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
> +			if (ret) {
> +				ffa_err("failed to read partition(s) data , error (%d)", ret);
> +				ffa_release_rx_buffer();
> +				return -EINVAL;
> +			}
> +		}
> +
> +		/*
> +		 * return the SP count (when querying using a UUID)
> +		 */
> +		if (pcount)
> +			*pcount = (u32)res.a2;
> +
> +		/*
> +		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
> +		 * is assigned to the consumer (u-boot). So, we need to give
> +		 * the ownership back to the SPM or hypervisor
> +		 */
> +		ret = ffa_release_rx_buffer();
> +
> +		return ret;
> +	}
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
> + *
> + * The passed arguments:
> + * Mode 1: When getting from the driver the number of
> + *	secure partitions:
> + *	@uuid_str: pointer to the UUID string
> + *	@parts_size: pointer to the variable that contains the number of partitions
> + *			 The variable will be set by the driver
> + *	@buffer: NULL
> + *
> + * Mode 2: When requesting the driver to return the
> + *	partitions information:
> + *	@uuid_str: pointer to the UUID string
> + *	@parts_size: pointer to the size of the SPs information buffer in bytes
> + *	@buffer: pointer to SPs information buffer
> + *		(allocated by the client).
> + *		The buffer will be filled by the driver
> + *
> + * This function queries the secure partition data from
> + * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
> + * FF-A function to query the partition information from secure world.
> + *
> + * A client of the FF-A driver should know the UUID of the service it wants to
> + * access. It should use the UUID to request the FF-A driver to provide the
> + * partition(s) information of the service. The FF-A driver uses
> + * PARTITION_INFO_GET to obtain this information. This is implemented through
> + * ffa_get_partitions_info function.
> + * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
> + * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
> + * They are not saved (already done). We only update the UUID in the cached area.
> + * This assumes that partitions data does not change in the secure world.
> + * Otherwise u-boot will have an outdated partition data. The benefit of caching
> + * the information in the FF-A driver is to accommodate discovery after
> + * ExitBootServices().
> + *
> + * When invoked through a client request, ffa_get_partitions_info should be
> + * called twice. First call is to get from the driver the number of secure
> + * partitions (SPs) associated to a particular UUID.
> + * Then, the caller (client) allocates the buffer to host the SPs data and
> + * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
> + * buffer.
> + *
> + * To achieve the mechanism described above, ffa_get_partitions_info uses the
> + * following functions:
> + *		ffa_read_partitions_info
> + *		ffa_query_partitions_info
> + *
> + * Return:
> + *
> + * @parts_size: When pointing to the number of partitions variable, the number is
> + * set by the driver.
> + * When pointing to the partitions information buffer size, the buffer will be
> + * filled by the driver.
> + *
> + * On success 0 is returned. Otherwise, failure
> + */
> +static int ffa_get_partitions_info(const char *uuid_str,
> +				   u32 *parts_size, struct ffa_partition_info *buffer)
> +{
> +	/*
> +	 * fill_data:
> +	 * 0: return the SP count
> +	 * 1: fill SP data and return it to the caller
> +	 * -1: undefined mode
> +	 */
> +	int fill_data = -1;
> +	u32 desc_idx, client_desc_idx;
> +	struct ffa_partition_uuid part_uuid = {0};
> +	u32 client_desc_max_cnt;
> +	u32 parts_found = 0;
> +
> +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
> +		ffa_err("no partition installed");
> +		return -EINVAL;
> +	}
> +
> +	if (!uuid_str) {
> +		ffa_err("no UUID provided");
> +		return -EINVAL;
> +	}
> +
> +	if (!parts_size) {
> +		ffa_err("no size/count provided");
> +		return -EINVAL;
> +	}
> +
> +	if (be_uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
> +		ffa_err("invalid UUID");
> +		return -EINVAL;
> +	}
> +
> +	if (!buffer) {
> +		/* Mode 1: getting the number of secure partitions */
> +
> +		fill_data = 0;
> +
> +		ffa_info("Preparing for checking partitions count");
> +
> +	} else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
> +		   !(*parts_size % sizeof(struct ffa_partition_info))) {
> +		/* Mode 2: retrieving the partitions information */
> +
> +		fill_data = 1;
> +
> +		client_desc_idx = 0;
> +
> +		/*
> +		 * number of empty descriptors preallocated by the caller
> +		 */
> +		client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
> +
> +		ffa_info("Preparing for filling partitions info");
> +
> +	} else {
> +		ffa_err("invalid function arguments provided");
> +		return -EINVAL;
> +	}
> +
> +	ffa_info("Searching partitions using the provided UUID");
> +
> +	/*
> +	 * search in the cached partitions
> +	 */
> +	for (desc_idx = 0;
> +	     desc_idx < ffa_priv_data->partitions.count;
> +	     desc_idx++) {
> +		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
> +					   &part_uuid)) {
> +			ffa_info("Partition ID %x matches the provided UUID",
> +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> +
> +			parts_found++;
> +
> +			if (fill_data) {
> +				/*
> +				 * trying to fill the partition info in the input buffer
> +				 */
> +
> +				if (client_desc_idx < client_desc_max_cnt) {
> +					buffer[client_desc_idx++] =
> +						ffa_priv_data->partitions.descs[desc_idx].info;
> +					continue;
> +				}
> +
> +				ffa_err("failed to fill the current descriptor client buffer full");
> +				return -ENOBUFS;
> +			}
> +		}
> +	}
> +
> +	if (!parts_found) {
> +		int ret;
> +
> +		ffa_info("No partition found. Querying framework ...");
> +
> +		ret = ffa_query_partitions_info(&part_uuid, &parts_found);
> +
> +		if (ret == 0) {
> +			if (!fill_data) {
> +				*parts_size = parts_found;
> +
> +				ffa_info("Number of partition(s) found matching the UUID: %d",
> +					 parts_found);
> +			} else {
> +				/*
> +				 * If SPs data detected, they are already in the private data
> +				 * structure, retry searching SP data again to return them
> +				 *  to the caller
> +				 */
> +				if (parts_found)
> +					ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
> +				else
> +					ret = -ENODATA;
> +			}
> +		}
> +
> +		return ret;
> +	}
> +
> +	/* partition(s) found */
> +	if (!fill_data)
> +		*parts_size = parts_found;
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_cache_partitions_info - Queries and saves all secure partitions data
> + *
> + * This function invokes FFA_PARTITION_INFO_GET FF-A
> + * function to query from secure world all partitions information.
> + *
> + * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
> + * All installed partitions information are returned. We cache them in the
> + * resident private data structure and we keep the UUID field empty
> + * (in FF-A 1.0 UUID is not provided by the partition descriptor)
> + *
> + * This function is called at the device probing level.
> + * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_cache_partitions_info(void)
> +{
> +	return ffa_query_partitions_info(NULL, NULL);
> +}
> +
> +/**
> + * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> + * @dst_part_id: destination partition ID
> + * @msg: pointer to the message data preallocated by the client (in/out)
> + *
> + * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * FF-A functions.
> + *
> + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> + * The response from the secure partition is handled by reading the
> + * FFA_MSG_SEND_DIRECT_RESP arguments.
> + *
> + * The maximum size of the data that can be exchanged is 40 bytes which is
> + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
> +		return -EINVAL;
> +
> +	/* No partition installed */
> +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
> +		return -ENODEV;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ),
> +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
> +				PREP_PART_ENDPOINT_ID(dst_part_id),
> +			.a2 = 0,
> +			.a3 = msg->data0,
> +			.a4 = msg->data1,
> +			.a5 = msg->data2,
> +			.a6 = msg->data3,
> +			.a7 = msg->data4,
> +			}, &res);
> +
> +	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
> +		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_RUN),
> +			.a1 = res.a1
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		/* Message sent with no response */
> +		return 0;
> +	}
> +
> +	if (res.a0 == FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP)) {
> +		/*
> +		 * Message sent with response
> +		 * extract the return data
> +		 */
> +		msg->data0 = res.a3;
> +		msg->data1 = res.a4;
> +		msg->data2 = res.a5;
> +		msg->data3 = res.a6;
> +		msg->data4 = res.a7;
> +
> +		return 0;
> +	}
> +
> +	ffa_errno = res.a2;
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * __arm_ffa_fn_smc - 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 low level SMC assembly function
> + *
> + * Return: void
> + */
> +void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
> +{
> +	arm_smccc_1_2_smc(&args, res);
> +}
> +
> +/**
> + * ffa_set_smc_conduit - Set the SMC conduit
> + *
> + * This function selects the SMC conduit by setting the driver invoke function
> + * to SMC assembly function
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_set_smc_conduit(void)
> +{
> +	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
> +
> +	if (!ffa_priv_data->invoke_ffa_fn) {
> +		ffa_err("failure to set the invoke function");
> +		return -EINVAL;
> +	}
> +
> +	ffa_info("Conduit is SMC");
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_set_bus_ops - Set the bus driver operations
> + *
> + * Setting the driver callbacks.
> + *
> + */
> +static void ffa_set_bus_ops(void)
> +{
> +	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
> +	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
> +	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
> +}
> +
> +/**
> + * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
> + * @dev:	the arm_ffa device
> + *
> + * This function creates the main data structure embedding all the driver data.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_alloc_prvdata(struct udevice *dev)
> +{
> +	if (!dev) {
> +		ffa_err("no udevice found");
> +		return -ENODEV;
> +	}
> +
> +	/* The device is registered with the DM. Let's create the driver main data structure*/
> +
> +	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
> +	if (!ffa_priv_data) {
> +		ffa_err("can not allocate the driver main data structure");
> +		return -ENOMEM;
> +	}
> +
> +	ffa_priv_data->dev = dev;
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_probe - The driver probe function
> + * @dev:	the arm_ffa device
> + *
> + * Probing is done at boot time and triggered by the uclass device discovery.
> + * At probe level the following actions are done:
> + *	- setting the conduit
> + *	- querying the FF-A framework version
> + *	- querying from secure world the u-boot endpoint ID
> + *	- querying from secure world the supported features of FFA_RXTX_MAP
> + *	- mapping the RX/TX buffers
> + *	- querying from secure world all the partitions information
> + *
> + * All data queried from secure world is saved in the resident private data structure.
> + *
> + * The probe will fail if either FF-A framework is not detected or the
> + * FF-A requests are not behaving correctly. This ensures that the
> + * driver is not installed and its operations are not exported to the clients.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_probe(struct udevice *dev)
> +{
> +	int ret;
> +
> +	ret = ffa_alloc_prvdata(dev);
> +	if (ret != 0)
> +		return ret;
> +
> +	ffa_set_bus_ops();
> +
> +	ret = ffa_set_smc_conduit();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_get_version();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_get_endpoint_id();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_get_rxtx_map_features();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_map_rxtx_buffers();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_cache_partitions_info();

I've asked this before, but never got an answer:
Why are we saving all the found partitions in a cache? It seems that
FFA_PARTITION_INFO_GET could be called each time when needed instead
without any noticeable overhead. Or is the result cached for some other
reason?

Cheers,
Jens

> +	if (ret != 0) {
> +		ffa_free_rxtx_buffers();
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_remove - The driver remove function
> + * @dev:	the arm_ffa device
> + * When the device is about to be removed ,  unmap the RX/TX buffers and free the memory
> + * Return:
> + *
> + * 0 on success.
> + */
> +static int ffa_remove(struct udevice *dev)
> +{
> +	ffa_info("removing the device");
> +
> +	ffa_unmap_rxtx_buffers();
> +
> +	if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
> +		ffa_free_rxtx_buffers();
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_unbind - The driver unbind function
> + * @dev:	the arm_ffa device
> + * After the device is removed and memory freed the device is unbound
> + * Return:
> + *
> + * 0 on success.
> + */
> +static int ffa_unbind(struct udevice *dev)
> +{
> +	ffa_info("unbinding the device , private data already released");
> +
> +	ffa_priv_data = NULL;
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_bus_ops_get - bus driver operations getter
> + *
> + * Return:
> + * This function returns a pointer to the driver operations structure
> + */
> +const struct ffa_bus_ops *ffa_bus_ops_get(void)
> +{
> +	return &ffa_priv_data->ffa_ops;
> +}
> +
> +/**
> + * ffa_bus_prvdata_get - bus driver private data getter
> + *
> + * Return:
> + * This function returns a pointer to the main private data structure
> + */
> +struct ffa_prvdata **ffa_bus_prvdata_get(void)
> +{
> +	return &ffa_priv_data;
> +}
> +
> +/**
> + * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
> + *
> + * 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 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.
> + * All FF-A clients should use the arm_ffa device to use the FF-A transport.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_bus_discover(void)
> +{
> +	int ret = 0;
> +
> +	if (!ffa_priv_data)
> +		ret = ffa_device_get();
> +
> +	return ret;
> +}
> +
> +/**
> + * Declaring the arm_ffa driver under UCLASS_FFA
> + */
> +
> +U_BOOT_DRIVER(arm_ffa) = {
> +	.name		= FFA_DRV_NAME,
> +	.id		= UCLASS_FFA,
> +	.probe		= ffa_probe,
> +	.remove		= ffa_remove,
> +	.unbind		= ffa_unbind,
> +};
> diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> new file mode 100644
> index 0000000000..d146e7b328
> --- /dev/null
> +++ b/include/arm_ffa.h
> @@ -0,0 +1,93 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#ifndef __ARM_FFA_H
> +#define __ARM_FFA_H
> +
> +#include <linux/printk.h>
> +
> +/*
> + * This header is public. It can be used by clients to access
> + * data structures and definitions they need
> + */
> +
> +/*
> + * Macros for displaying logs
> + */
> +
> +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> +
> +/*
> + * struct ffa_partition_info - Partition information descriptor
> + * @id:	Partition ID
> + * @exec_ctxt:	Execution context count
> + * @properties:	Partition properties
> + *
> + * Data structure containing information about partitions instantiated in the system
> + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> + */
> +struct  __packed ffa_partition_info {
> +	u16 id;
> +	u16 exec_ctxt;
> +/* partition supports receipt of direct requests */
> +#define FFA_PARTITION_DIRECT_RECV	BIT(0)
> +/* partition can send direct requests. */
> +#define FFA_PARTITION_DIRECT_SEND	BIT(1)
> +/* partition can send and receive indirect messages. */
> +#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
> +	u32 properties;
> +};
> +
> +/*
> + * struct ffa_send_direct_data - Data structure hosting the data
> + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * @data0-4:	Data read/written from/to x3-x7 registers
> + *
> + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> + * or read from FFA_MSG_SEND_DIRECT_RESP
> + */
> +
> +/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
> +struct __packed ffa_send_direct_data {
> +	unsigned long data0; /* w3/x3 */
> +	unsigned long data1; /* w4/x4 */
> +	unsigned long data2; /* w5/x5 */
> +	unsigned long data3; /* w6/x6 */
> +	unsigned long data4; /* w7/x7 */
> +};
> +
> +/**
> + * struct ffa_bus_ops - The driver operations structure
> + * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
> + * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
> + * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
> + *
> + * The data structure providing all the operations supported by the driver.
> + * This structure is EFI runtime resident.
> + */
> +struct ffa_bus_ops {
> +	int (*partition_info_get)(const char *uuid_str,
> +				  u32 *parts_size, struct ffa_partition_info *buffer);
> +	int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg);
> +	int (*rxtx_unmap)(void);
> +};
> +
> +/**
> + * The device driver and the Uclass driver public functions
> + */
> +
> +/**
> + * ffa_bus_ops_get - driver operations getter
> + */
> +const struct ffa_bus_ops *ffa_bus_ops_get(void);
> +
> +/**
> + * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
> + */
> +int ffa_bus_discover(void);
> +
> +#endif
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index a432e43871..5dd698b7a9 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -4,6 +4,9 @@
>   *
>   * (C) Copyright 2012
>   * Pavel Herrmann <morpheus.ibis@gmail.com>
> + *
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #ifndef _DM_UCLASS_ID_H
> @@ -55,6 +58,7 @@ enum uclass_id {
>  	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
>  	UCLASS_ETH,		/* Ethernet device */
>  	UCLASS_ETH_PHY,		/* Ethernet PHY device */
> +	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
>  	UCLASS_FIRMWARE,	/* Firmware */
>  	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
>  	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-10-25  9:31                                       ` Jens Wiklander
@ 2022-10-25 10:27                                         ` Abdellatif El Khlifi
  2022-11-08 11:28                                         ` Abdellatif El Khlifi
  1 sibling, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-10-25 10:27 UTC (permalink / raw)
  To: Jens Wiklander; +Cc: u-boot, nd

On Tue, Oct 25, 2022 at 11:31:11AM +0200, Jens Wiklander wrote:
> On Thu, Oct 13, 2022 at 11:38:50AM +0100, Abdellatif El Khlifi wrote:
> > Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0
> > 
> > The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> > describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World leveraging TrustZone
> > technology.
> > 
> > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > querying the FF-A framework from the secure world.
> > 
> > 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> > and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> > 
> > In u-boot FF-A design, FF-A is considered as a discoverable bus.
> 
> U-Boot
> 
> > The Secure World is considered as one entity to communicate with
> > using the FF-A bus. FF-A communication is handled by one device and
> > one instance (the bus). This FF-A driver takes care of all the
> > interactions between Normal world and Secure World.
> > 
> > The driver exports its operations to be used by upper layers.
> > 
> > Exported operations:
> > 
> > - partition_info_get
> > - sync_send_receive
> > - rxtx_unmap
> > 
> > [1]: https://developer.arm.com/documentation/den0077/latest/
> > 
> > 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>
> > 
> > ---
> > 
> > Changelog:
> > ===============
> > 
> > v6:
> > 
> > * drop use of EFI runtime support (We decided with Linaro to add this later)
> > * drop discovery from initcalls (discovery will be on demand by FF-A users)
> > * set the alignment of the RX/TX buffers to the larger translation granule size
> > * move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
> > * update the documentation and move it to doc/arch/arm64.ffa.rst
> > 
> > v4:
> > 
> > * add doc/README.ffa.drv
> > * moving the FF-A driver work to drivers/firmware/arm-ffa
> > * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
> >   #if defined by #if CONFIG_IS_ENABLED
> > * improving error handling by mapping the FF-A errors to standard errors
> >   and logs
> > * replacing panics with an error log and returning an error code
> > * improving features discovery in FFA_FEATURES by introducing
> >   rxtx_min_pages private data field
> > * add ffa_remove and ffa_unbind functions
> > * improve how the driver behaves when bus discovery is done more than
> >   once
> > 
> > v3:
> > 
> > * align the interfaces of the u-boot FF-A driver with those in the linux
> >   FF-A driver
> > * remove the FF-A helper layer
> > * make the u-boot FF-A driver independent from EFI
> > * provide an optional config that enables copying the driver data to EFI
> >   runtime section at ExitBootServices service
> > * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
> > 
> > v2:
> > 
> > * make FF-A bus discoverable using device_{bind, probe} APIs
> > * remove device tree support
> > 
> > v1:
> > 
> > * introduce FF-A bus driver with device tree support
> > 
> >  MAINTAINERS                               |    7 +
> >  doc/arch/arm64.ffa.rst                    |  207 ++++
> >  doc/arch/index.rst                        |    1 +
> >  drivers/Kconfig                           |    2 +
> >  drivers/Makefile                          |    1 +
> >  drivers/firmware/arm-ffa/Kconfig          |   30 +
> >  drivers/firmware/arm-ffa/Makefile         |    6 +
> >  drivers/firmware/arm-ffa/arm-ffa-uclass.c |   16 +
> >  drivers/firmware/arm-ffa/arm_ffa_prv.h    |  196 +++
> >  drivers/firmware/arm-ffa/core.c           | 1337 +++++++++++++++++++++
> >  include/arm_ffa.h                         |   93 ++
> >  include/dm/uclass-id.h                    |    4 +
> >  12 files changed, 1900 insertions(+)
> >  create mode 100644 doc/arch/arm64.ffa.rst
> >  create mode 100644 drivers/firmware/arm-ffa/Kconfig
> >  create mode 100644 drivers/firmware/arm-ffa/Makefile
> >  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
> >  create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
> >  create mode 100644 drivers/firmware/arm-ffa/core.c
> >  create mode 100644 include/arm_ffa.h
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index a26b36c7c2..496f47a516 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -248,6 +248,13 @@ F:	drivers/net/cortina_ni.h
> >  F:	drivers/net/phy/ca_phy.c
> >  F:	configs/cortina_presidio-asic-pnand_defconfig
> >  
> > +ARM FF-A
> > +M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > +S:	Maintained
> > +F:	doc/arch/arm64.ffa.rst
> > +F:	drivers/firmware/arm-ffa/
> > +F:	include/arm_ffa.h
> > +
> >  ARM FREESCALE IMX
> >  M:	Stefano Babic <sbabic@denx.de>
> >  M:	Fabio Estevam <festevam@gmail.com>
> > diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> > new file mode 100644
> > index 0000000000..e98d2cf2b3
> > --- /dev/null
> > +++ b/doc/arch/arm64.ffa.rst
> > @@ -0,0 +1,207 @@
> > +.. SPDX-License-Identifier: GPL-2.0+
> > +
> > +Arm FF-A Driver
> > +===============
> > +
> > +Summary
> > +-------
> > +
> > +FF-A stands for Firmware Framework for Arm A-profile processors.
> > +
> > +FF-A specifies interfaces that enable a pair of software sandboxes to
> > +communicate with each other. A sandbox aka partition could
> > +be a VM in the Normal or Secure world, an application in S-EL0, or a
> > +Trusted OS in S-EL1.
> > +
> > +This FF-A driver implements the interfaces to communicate with partitions in
> > +the Secure world aka Secure partitions (SPs).
> > +
> > +The driver specifically focuses on communicating with SPs that isolate portions
> > +of EFI runtime services that must run in a protected environment which is
> > +inaccessible by the Host OS or Hypervisor. Examples of such services are
> > +set/get variables.
> > +
> > +FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> > +
> > +- Discover the presence of SPs of interest
> > +- Access an SP's service through communication protocols
> > +  e.g. EFI MM communication protocol
> > +
> > +FF-A and SMC specifications
> > +-------------------------------------------
> > +
> > +The current implementation of the driver relies on FF-A specification v1.0
> > +and uses SMC32 calling convention.
> > +
> > +At this stage we only need the FF-A v1.0 features.
> > +
> > +The driver has been tested with Optee OS which supports SMC32 for most of
> 
> s/Optee OS/OP-TEE/
> 
> > +the SMC ABIs.
> > +
> > +For more details please refer to the FF-A v1.0 spec:
> > +https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=
> > +
> > +Hypervisors are supported if they are configured to trap SMC calls.
> > +
> > +The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
> > +
> > +For more details please refer to the SMC Calling Convention v1.2 spec:
> > +https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
> > +
> > +Supported hardware
> > +--------------------------------
> > +
> > +Aarch64 plaforms
> > +
> > +Configuration
> > +----------------------
> > +
> > +CONFIG_ARM_FFA_TRANSPORT
> > +    Enables the FF-A bus driver. Turn this on if you want to use FF-A
> > +    communication.
> > +
> > +CONFIG_SANDBOX_FFA
> > +    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
> > +    Sandbox and provides functional tests for FF-A.
> > +
> > +FF-A ABIs under the hood
> > +---------------------------------------
> > +
> > +Invoking an FF-A ABI involves providing to the secure world/hypervisor the
> > +expected arguments from the ABI.
> > +
> > +The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction
> > +is executed.
> > +
> > +At the secure side level or hypervisor the ABI is handled at a higher exception
> > +level and the arguments are read and processed.
> > +
> > +The response is put back through x0 to x7 registers and control is given back
> > +to the U-boot FF-A driver (non-secure world).
> > +
> > +The driver reads the response and processes it accordingly.
> > +
> > +This methodology applies to all the FF-A ABIs in the driver.
> > +
> > +FF-A bus discovery in U-boot
> 
> U-Boot, please search and replace.
> 
> > +-------------------------------------------
> > +
> > +When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is discovered on
> > +demand by the clients (users).
> > +
> > +Clients can discover the FF-A bus using ffa_bus_discover() API which triggers the
> > +discovery process.
> > +
> > +ffa_bus_discover() creates, binds and probes the arm_ffa device using
> > +device_{bind, probe} APIs.
> > +
> > +The discovery process consists in communicating with secure world (or hypervisor)
> > +and querying specific data.
> > +
> > +The discovery process takes place during the arm_ffa device probing which is
> > +handled by ffa_probe().
> > +
> > +The FF-A bus discovery is successful and the bus is ready for use when these
> > +operations succeed:
> > +
> > +- querying the FF-A framework version
> > +- querying from secure world the U-boot endpoint ID
> > +- querying from secure world the RX/TX mapping  features
> > +- mapping the RX/TX buffers
> > +- querying from secure world all the partitions information
> > +
> > +Discovery failure results in a probing failure and the arm_ffa device is
> > +destroyed.
> > +
> > +Requirements for clients
> > +-------------------------------------
> > +
> > +When using the FF-A bus with EFI, clients must:
> > +
> > +- Query SPs in EFI boot time mode using the service UUID.
> > +- Unmap RX/TX buffers before EFI runtime mode starts.
> > +
> > +The RX/TX buffers are only available at EFI boot time. Querying partitions is
> > +done at boot time and data is cached for future use.
> > +
> > +RX/TX buffers should be unmapped by the user before EFI runtime mode
> > +starts. The driver provides a bus operation for that: rxtx_unmap()
> > +
> > +If  RX/TX buffers created by U-boot are not unmapped and by
> > +consequence becoming available at EFI runtime, secure world will get confused
> > +about RX/TX buffers ownership (U-boot vs kernel).
> > +
> > +The bus driver layer
> > +------------------------------
> > +
> > +The driver comes on top of the SMCCC layer and is implemented in
> > +drivers/firmware/arm-ffa/core.c
> > +
> > +The driver provides the following features:
> > +
> > +- Support for the 32-bit version of the following ABIs:
> > +
> > +FFA_VERSION
> > +FFA_ID_GET
> > +FFA_FEATURES
> > +FFA_PARTITION_INFO_GET
> > +FFA_RXTX_UNMAP
> > +FFA_RX_RELEASE
> > +FFA_RUN
> > +FFA_ERROR
> > +FFA_SUCCESS
> > +FFA_INTERRUPT
> > +
> > +- Support for the 64-bit version of the following ABIs:
> > +
> > +FFA_RXTX_MAP
> > +FFA_MSG_SEND_DIRECT_REQ
> > +FFA_MSG_SEND_DIRECT_RESP
> > +
> > +- Processing the received data from the secure world/hypervisor and caching it
> > +
> > +- Hiding from upper layers the FF-A protocol and registers details. Upper
> > +  layers focus on exchanged data, the driver takes care of how to transport
> > +  that to the secure world/hypervisor using FF-A
> > +
> > +- The driver provides callbacks to be used by clients to access the FF-A bus:
> > +
> > +partition_info_get
> > +sync_send_receive
> > +rxtx_unmap
> > +
> > +- FF-A bus discovery makes sure FF-A framework is responsive and compatible
> > +  with the driver
> > +
> > +- FF-A bus can be compiled and used without EFI
> > +
> > +Using armffa command
> > +-----------------------------------
> > +
> > +armffa is a command showcasing how to use the FF-A driver and how to invoke
> > +its operations.
> > +
> > +This provides a guidance to the client developers on how to call the FF-A bus
> > +interfaces.
> > +
> > +Usage:
> > +
> > +armffa <sub-command> <arguments>
> > +
> > +sub-commands:
> > +
> > +        getpart <partition UUID>
> > +
> > +            lists the partition(s) info
> > +
> > +        ping <partition ID>
> > +
> > +            sends a data pattern to the specified partition
> 
> It may be worth mentioning that this is an implementation defined
> command.
> 
> > +
> > +        devlist
> > +
> > +            displays the arm_ffa device info
> > +
> > +Contributors
> > +------------
> > +   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > diff --git a/doc/arch/index.rst b/doc/arch/index.rst
> > index 792d9182c3..8d1ab0ad4e 100644
> > --- a/doc/arch/index.rst
> > +++ b/doc/arch/index.rst
> > @@ -8,6 +8,7 @@ Architecture-specific doc
> >  
> >     arc
> >     arm64
> > +   arm64.ffa
> >     m68k
> >     mips
> >     nios2
> > diff --git a/drivers/Kconfig b/drivers/Kconfig
> > index 8b6fead351..b06b1ae481 100644
> > --- a/drivers/Kconfig
> > +++ b/drivers/Kconfig
> > @@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
> >  
> >  source "drivers/adc/Kconfig"
> >  
> > +source "drivers/firmware/arm-ffa/Kconfig"
> > +
> >  source "drivers/ata/Kconfig"
> >  
> >  source "drivers/axi/Kconfig"
> > diff --git a/drivers/Makefile b/drivers/Makefile
> > index 9d9f69a3c9..bf8d7b8cfc 100644
> > --- a/drivers/Makefile
> > +++ b/drivers/Makefile
> > @@ -111,6 +111,7 @@ obj-y += iommu/
> >  obj-y += smem/
> >  obj-y += thermal/
> >  obj-$(CONFIG_TEE) += tee/
> > +obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
> >  obj-y += axi/
> >  obj-y += ufs/
> >  obj-$(CONFIG_W1) += w1/
> > diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> > new file mode 100644
> > index 0000000000..f1427535f9
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/Kconfig
> > @@ -0,0 +1,30 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +config ARM_FFA_TRANSPORT
> > +	bool "Enable Arm Firmware Framework for Armv8-A driver"
> > +	depends on DM && ARM64
> > +	select ARM_SMCCC
> > +	select LIB_UUID
> > +	select DEVRES
> > +	help
> > +	  The Firmware Framework for Arm A-profile processors (FF-A)
> > +	  describes interfaces (ABIs) that standardize communication
> > +	  between the Secure World and Normal World leveraging TrustZone
> > +	  technology.
> > +
> > +	  This driver is based on FF-A specification v1.0 and uses SMC32
> > +	  calling convention.
> > +
> > +	  FF-A specification:
> > +
> > +	  https://developer.arm.com/documentation/den0077/a/?lang=en
> > +
> > +	  In u-boot FF-A design, FF-A is considered as a discoverable bus.
> 
> U-Boot
> 
> > +	  The Secure World is considered as one entity to communicate with
> > +	  using the FF-A bus.
> > +	  FF-A communication is handled by one device and one instance (the bus).
> > +	  This FF-A driver takes care of all the interactions between Normal world
> > +	  and Secure World.
> > +
> > +	  For more details about the FF-A driver, please refer to doc/README.ffa.drv
> 
> Not doc/arch/arm64.ffa.rst?
> 
> > +
> > diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
> > new file mode 100644
> > index 0000000000..043a8915be
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/Makefile
> > @@ -0,0 +1,6 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +#
> > +# (C) Copyright 2022
> > +# Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com.
> > +
> > +obj-y += arm-ffa-uclass.o core.o
> > diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> > new file mode 100644
> > index 0000000000..7d9695d289
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> > @@ -0,0 +1,16 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <asm/global_data.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +UCLASS_DRIVER(ffa) = {
> > +	.name		= "ffa",
> > +	.id		= UCLASS_FFA,
> > +};
> > diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> > new file mode 100644
> > index 0000000000..7bc90f7f66
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> > @@ -0,0 +1,196 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_PRV_H
> > +#define __ARM_FFA_PRV_H
> > +
> > +#include <arm_ffa.h>
> > +#include <linux/bitfield.h>
> > +#include <linux/bitops.h>
> > +#include <linux/arm-smccc.h>
> > +
> > +/*
> > + * This header is private. It is exclusively used by the FF-A driver
> > + */
> > +
> > +/* FF-A core driver name */
> > +#define FFA_DRV_NAME "arm_ffa"
> > +
> > +/* FF-A driver version definitions */
> > +
> > +#define MAJOR_VERSION_MASK		GENMASK(30, 16)
> > +#define MINOR_VERSION_MASK		GENMASK(15, 0)
> > +#define GET_FFA_MAJOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> > +#define GET_FFA_MINOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> > +#define PACK_VERSION_INFO(major, minor)			\
> > +	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
> > +	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> > +
> > +#define FFA_MAJOR_VERSION		(1)
> > +#define FFA_MINOR_VERSION		(0)
> > +#define FFA_VERSION_1_0		\
> > +			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> > +
> > +/* Endpoint ID mask (u-boot endpoint ID) */
> > +
> > +#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define GET_SELF_ENDPOINT_ID(x)		\
> > +			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> > +
> > +#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
> > +#define PREP_SELF_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> > +
> > +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> > +
> > +#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define PREP_PART_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> > +
> > +/*
> > + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> > + */
> > +
> > +#define FFA_SMC(calling_convention, func_num)				\
> > +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
> > +			   ARM_SMCCC_OWNER_STANDARD, (func_num))
> > +
> > +#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> > +#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
> > +
> > +enum ffa_abis {
> > +	FFA_ERROR					= 0x60,
> > +	FFA_SUCCESS					= 0x61,
> > +	FFA_INTERRUPT				= 0x62,
> > +	FFA_VERSION					= 0x63,
> > +	FFA_FEATURES				= 0x64,
> > +	FFA_RX_RELEASE				= 0x65,
> > +	FFA_RXTX_MAP				= 0x66,
> > +	FFA_RXTX_UNMAP			= 0x67,
> > +	FFA_PARTITION_INFO_GET		= 0x68,
> > +	FFA_ID_GET					= 0x69,
> > +	FFA_RUN						= 0x6D,
> > +	FFA_MSG_SEND_DIRECT_REQ	= 0x6F,
> > +	FFA_MSG_SEND_DIRECT_RESP	= 0x70,
> > +
> > +	/* to be updated when adding new FFA IDs */
> > +	FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
> > +	FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
> > +};
> > +
> > +/* number of the errors supported by the FF-A specification */
> > +#define MAX_NUMBER_FFA_ERR 9
> > +
> > +/* container structure and helper macros to map between an FF-A error and relevant error log */
> > +struct ffa_abi_errmap {
> > +	char *err_str[MAX_NUMBER_FFA_ERR];
> > +};
> > +
> > +#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
> > + *
> > + */
> > +struct ffa_partition_uuid {
> > +	u32 a1; /* w1 */
> > +	u32 a2; /* w2 */
> > +	u32 a3; /* w3 */
> > +	u32 a4; /* w4 */
> > +};
> > +
> > +/**
> > + * enum ffa_rxtx_buf_sizes - minimum sizes supported
> > + * for the RX/TX buffers
> > + */
> > +enum ffa_rxtx_buf_sizes {
> > +	RXTX_4K,
> > +	RXTX_64K,
> > +	RXTX_16K
> > +};
> > +
> > +/**
> > + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> > + * @rxbuf:	virtual address of the RX buffer
> > + * @txbuf:	virtual address of the TX buffer
> > + * @rxtx_min_pages:	RX/TX buffers minimum size in pages
> > + *
> > + * Data structure hosting the virtual addresses of the mapped RX/TX buffers
> > + * These addresses are used by the FF-A functions that use the RX/TX buffers
> > + */
> > +struct ffa_rxtxpair {
> > +	u64 rxbuf; /* virtual address */
> > +	u64 txbuf; /* virtual address */
> > +	size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
> > +};
> > +
> > +/**
> > + * struct ffa_partition_desc - the secure partition descriptor
> > + * @info:	partition information
> > + * @sp_uuid:	the secure partition UUID
> > + *
> > + * Each partition has its descriptor containing the partitions information and the UUID
> > + */
> > +struct ffa_partition_desc {
> > +	struct ffa_partition_info info;
> > +	struct ffa_partition_uuid sp_uuid;
> > +};
> > +
> > +/**
> > + * struct ffa_partitions - descriptors for all secure partitions
> > + * @count:	The number of partitions descriptors
> > + * @descs	The partitions descriptors table
> > + *
> > + * This data structure contains the partitions descriptors table
> > + */
> > +struct ffa_partitions {
> > +	u32 count;
> > +	struct ffa_partition_desc *descs; /* virtual address */
> > +};
> > +
> > +/**
> > + * struct ffa_prvdata - the driver private data structure
> > + *
> > + * @dev:	The arm_ffa device under u-boot driver model
> > + * @ffa_ops:	The driver operations structure
> > + * @fwk_version:	FF-A framework version
> > + * @id:	u-boot endpoint ID
> > + * @partitions:	The partitions descriptors structure
> > + * @pair:	The RX/TX buffers pair
> > + * @invoke_ffa_fn:	The function executing the FF-A function
> > + *
> > + * The driver data structure hosting all resident data.
> > + */
> > +struct ffa_prvdata {
> > +	struct udevice *dev;
> > +	struct ffa_bus_ops ffa_ops;
> > +	u32 fwk_version;
> > +	u16 id;
> > +	struct ffa_partitions partitions;
> > +	struct ffa_rxtxpair pair;
> > +	invoke_ffa_fn_t invoke_ffa_fn;
> > +};
> > +
> > +/**
> > + * ffa_device_get - create, bind and probe the arm_ffa device
> > + */
> > +int ffa_device_get(void);
> > +
> > +/**
> > + * ffa_bus_prvdata_get - bus driver private data getter
> > + */
> > +struct ffa_prvdata **ffa_bus_prvdata_get(void);
> > +
> > +#endif
> > diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
> > new file mode 100644
> > index 0000000000..324367d12b
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/core.c
> > @@ -0,0 +1,1337 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include "arm_ffa_prv.h"
> > +#include <asm/global_data.h>
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <dm/device-internal.h>
> > +#include <dm/devres.h>
> > +#include <dm/root.h>
> > +#include <linux/errno.h>
> > +#include <linux/sizes.h>
> > +#include <log.h>
> > +#include <malloc.h>
> > +#include <string.h>
> > +#include <uuid.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/**
> > + * The device private data structure containing all the
> > + * data read from secure world
> > + */
> > +struct ffa_prvdata *ffa_priv_data;
> > +
> > +/* Error mapping declarations */
> > +
> > +int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
> > +	0,
> > +	-EOPNOTSUPP,	/* NOT_SUPPORTED */
> > +	-EINVAL,	/* INVALID_PARAMETERS */
> > +	-ENOMEM,	/* NO_MEMORY */
> > +	-EBUSY,		/* BUSY */
> > +	-EINTR,		/* INTERRUPTED */
> > +	-EACCES,	/* DENIED */
> > +	-EAGAIN,	/* RETRY */
> > +	-ECANCELED,	/* ABORTED */
> > +};
> > +
> > +struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
> > +		{
> > +			"",
> 
> Shouldn't all these empty strings be NULL instead? Given that's that
> what you check for in ffa_print_error_log() below.
> 
> You could save a few lines by using designated initializers for only the
> used elements in err_str for each FF-A function ID.
> 
> > +			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
> > +			"", /* INVALID_PARAMETERS */
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"", /* DENIED */
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
> > +		{
> > +			"",
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +			"", /* INVALID_PARAMETERS */
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"", /* DENIED */
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
> > +		{
> > +			"",
> > +			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
> > +			"", /* INVALID_PARAMETERS */
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"", /* DENIED */
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
> > +		{
> > +			"",
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +			"INVALID_PARAMETERS: Unrecognized UUID",
> > +			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
> > +			"BUSY: RX buffer of the caller is not free",
> > +			"", /* INTERRUPTED */
> > +			"DENIED: Callee is not in a state to handle this request",
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
> > +			{
> > +			"",
> > +			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
> > +			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"", /* DENIED */
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
> > +			{
> > +			"",
> > +			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
> > +			"", /* INVALID_PARAMETERS */
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"DENIED: Caller did not have ownership of the RX buffer",
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
> > +			{
> > +			"",
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
> > +			"NO_MEMORY: Not enough memory",
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"DENIED: Buffer pair already registered",
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +};
> > +
> > +/**
> > + * ffa_to_std_errno - convert FF-A error code to standard error code
> > + * @ffa_errno:	Error code returned by the FF-A ABI
> > + *
> > + * This function maps the given FF-A error code as specified
> > + * by the spec to a u-boot standard error code.
> > + *
> > + * Return:
> > + *
> > + * The standard error code on success. . Otherwise, failure
> > + */
> > +int ffa_to_std_errno(int ffa_errno)
> > +{
> > +	int err_idx = -ffa_errno;
> > +
> > +	/* map the FF-A error code to the standard u-boot error code */
> > +	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
> > +		return ffa_to_std_errmap[err_idx];
> > +	return -EINVAL;
> > +}
> > +
> > +/**
> > + * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
> > + * @ffa_id:	FF-A ABI ID
> > + * @ffa_errno:	Error code returned by the FF-A ABI
> > + *
> > + * This function maps the FF-A error code to the error log relevant to the
> > + * selected FF-A ABI. Then the error log is printed.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. . Otherwise, failure
> > + */
> > +int ffa_print_error_log(u32 ffa_id, int ffa_errno)
> > +{
> > +	int err_idx = -ffa_errno, abi_idx = 0;
> > +
> > +	/* map the FF-A error code to the corresponding error log */
> > +
> > +	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
> > +		return -EINVAL;
> > +
> > +	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
> > +		return -EINVAL;
> > +
> > +	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
> > +	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
> > +		return -EINVAL;
> > +
> > +	if (!err_msg_map[abi_idx].err_str || !err_msg_map[abi_idx].err_str[err_idx])
> 
> err_str can't be NULL since it's an array in the struct ffa_abi_errmap.
> 
> > +		return -EINVAL;
> > +
> > +	ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Driver core functions
> > + */
> > +
> > +/**
> > + * ffa_remove_device - removes the arm_ffa device
> > + * @dev:	the device to be removed
> > + *
> > + * This function makes sure the arm_ffa device is removed
> > + * No need to free the kmalloced data when the device is destroyed.
> > + * It's automatically done by devm management by
> > + * device_remove() -> device_free() -> devres_release_probe().
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_remove_device(struct udevice *dev)
> > +{
> > +	int ret;
> > +
> > +	if (!dev) {
> > +		ffa_err("no udevice found");
> > +		return -ENODEV;
> > +	}
> > +
> > +	ret = device_remove(dev, DM_REMOVE_NORMAL);
> > +	if (ret) {
> > +		ffa_err("unable to remove. err:%d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	ffa_info("device removed and freed");
> > +
> > +	ret = device_unbind(dev);
> > +	if (ret) {
> > +		ffa_err("unable to unbind. err:%d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	ffa_info("device unbound");
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_device_get - create, bind and probe the arm_ffa device
> > + *
> > + * This function makes sure the arm_ffa device is
> > + * created, bound to this driver, probed and ready to use.
> > + * Arm FF-A transport is implemented through a single u-boot
> > + * device managing the FF-A bus (arm_ffa).
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_device_get(void)
> > +{
> > +	int ret;
> > +	struct udevice *dev = NULL;
> > +
> > +	ret = device_bind(dm_root(),
> > +			  DM_DRIVER_GET(arm_ffa),
> > +			  FFA_DRV_NAME,
> > +			  NULL,
> > +			  ofnode_null(),
> > +			  &dev);
> 
> There's no need for separate lines for each argument, please fold up a bit.
> 
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* The FF-A bus discovery succeeds when probing is successful */
> > +	ret = device_probe(dev);
> > +	if (ret) {
> > +		ffa_err("arm_ffa device probing failed");
> > +		ffa_remove_device(dev);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_get_version - FFA_VERSION handler function
> > + *
> > + * This function implements FFA_VERSION FF-A function
> > + * to get from the secure world the FF-A framework version
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_version(void)
> > +{
> > +	u16 major, minor;
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_VERSION),
> > +			.a1 = FFA_VERSION_1_0
> 
> It's generally preferred to have comma after the last initializer too.
> 
> It could also be worth comparing with the style (alignment and folding
> up where possible) of the corresponding driver in the Linux kernel which
> I find a bit easier to read. However, checkpatch seems happy enough so I
> guess it's not a big deal.
> 
> I asked earlier why you're not supporting the latest version, 1.1, but
> you never answered that.

Thanks for all the new comments. I'll address these in v7.

Regarding you older comments, I already replied here [1]. Please have a look.

[1]: https://lore.kernel.org/all/20221014102849.GA14576@e121910.cambridge.arm.com/

> 
> > +			}, &res);
> > +
> > +	ffa_errno = res.a0;
> > +	if (ffa_errno < 0) {
> > +		ffa_print_error_log(FFA_VERSION, ffa_errno);
> > +		return ffa_to_std_errno(ffa_errno);
> > +	}
> > +
> > +	major = GET_FFA_MAJOR_VERSION(res.a0);
> > +	minor = GET_FFA_MINOR_VERSION(res.a0);
> > +
> > +	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> > +		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
> > +		ffa_info("Versions are compatible ");
> > +
> > +		ffa_priv_data->fwk_version = res.a0;
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
> > +		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +	return -EPROTONOSUPPORT;
> > +}
> > +
> > +/**
> > + * ffa_get_endpoint_id - FFA_ID_GET handler function
> > + *
> > + * This function implements FFA_ID_GET FF-A function
> > + * to get from the secure world u-boot endpoint ID
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_endpoint_id(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_ID_GET)
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
> > +		ffa_info("endpoint ID is %u", ffa_priv_data->id);
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +
> > +	ffa_print_error_log(FFA_ID_GET, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
> > + * @prop_field: properties field obtained from FFA_FEATURES ABI
> > + *
> > + * This function sets the minimum number of pages
> > + *  in each of the RX/TX buffers in the private data structure
> > + *
> > + * Return:
> > + *
> > + * buf_4k_pages points to the returned number of pages
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
> > +{
> > +	if (!ffa_priv_data)
> > +		return -EINVAL;
> > +
> > +	switch (prop_field) {
> > +	case RXTX_4K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 1;
> > +		break;
> > +	case RXTX_16K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 4;
> > +		break;
> > +	case RXTX_64K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 16;
> > +		break;
> > +	default:
> > +		ffa_err("RX/TX buffer size not supported");
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
> > + *
> > + * This function implements FFA_FEATURES FF-A function
> > + * to retrieve the FFA_RXTX_MAP features
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_rxtx_map_features(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_FEATURES),
> > +			.a1 = FFA_SMC_64(FFA_RXTX_MAP)
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> > +		return ffa_set_rxtx_buffers_pages_cnt((u32)res.a2);
> 
> The cast isn't needed.
> 
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_FEATURES, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> > + *
> > + * This  function  frees the RX/TX buffers
> > + *
> > + */
> > +static void ffa_free_rxtx_buffers(void)
> > +{
> > +	ffa_info("Freeing RX/TX buffers");
> > +
> > +	if (ffa_priv_data->pair.rxbuf) {
> > +		free((void *)ffa_priv_data->pair.rxbuf);
> > +		ffa_priv_data->pair.rxbuf = 0;
> > +	}
> > +
> > +	if (ffa_priv_data->pair.txbuf) {
> > +		free((void *)ffa_priv_data->pair.txbuf);
> > +		ffa_priv_data->pair.txbuf = 0;
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
> > + *
> > + * This function is used by ffa_map_rxtx_buffers to allocate
> > + * the RX/TX buffers before mapping them. The allocated memory is physically
> > + * contiguous since memalign ends up calling malloc which allocates
> > + * contiguous memory in u-boot.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_alloc_rxtx_buffers(void)
> > +{
> > +	u64 bytes;
> > +
> > +	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
> > +		 ffa_priv_data->pair.rxtx_min_pages);
> > +
> > +	bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> > +
> > +	/*
> > +	 * The alignment of the RX and TX buffers must be equal
> > +	 * to the larger translation granule size
> > +	 */
> > +
> > +	ffa_priv_data->pair.rxbuf = (u64)memalign(bytes, bytes);
> > +	if (!ffa_priv_data->pair.rxbuf) {
> > +		ffa_err("failure to allocate RX buffer");
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
> > +
> > +	ffa_priv_data->pair.txbuf = (u64)memalign(bytes, bytes);
> > +	if (!ffa_priv_data->pair.txbuf) {
> > +		free((void *)ffa_priv_data->pair.rxbuf);
> > +		ffa_priv_data->pair.rxbuf = 0;
> > +		ffa_err("failure to allocate the TX buffer");
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
> > +
> > +	/*
> > +	 * make sure the buffers are cleared before use
> > +	 */
> > +	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
> > +	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> > + *
> > + * This function implements FFA_RXTX_MAP FF-A function
> > + * to map the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_map_rxtx_buffers(void)
> > +{
> > +	int ret;
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ret = ffa_alloc_rxtx_buffers();
> > +	if (ret)
> > +		return ret;
> > +
> > +	/*
> > +	 * we need to pass the physical addresses of the RX/TX buffers
> > +	 * in u-boot physical/virtual mapping is 1:1
> > +	 *no need to convert from virtual to physical
> 
> A space is missing after the '*'.
> 
> > +	 */
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
> > +			.a1 = ffa_priv_data->pair.txbuf,
> > +			.a2 = ffa_priv_data->pair.rxbuf,
> > +			.a3 = ffa_priv_data->pair.rxtx_min_pages,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_info("RX/TX buffers mapped");
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
> > +
> > +	ffa_free_rxtx_buffers();
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
> > + *
> > + * This function implements FFA_RXTX_UNMAP FF-A function
> > + * to unmap the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_unmap_rxtx_buffers(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
> > +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id)
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_free_rxtx_buffers();
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
> > + *
> > + * This function invokes FFA_RX_RELEASE FF-A function
> > + * to release the ownership of the RX buffer
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_release_rx_buffer(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RX_RELEASE)
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> > +		return 0;
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_uuid_are_identical - checks whether two given UUIDs are identical
> > + * @uuid1: first UUID
> > + * @uuid2: second UUID
> > + *
> > + * This function is used by ffa_read_partitions_info to search
> > + * for a UUID in the partitions descriptors table
> > + *
> > + * Return:
> > + *
> > + * 1 when UUIDs match. Otherwise, 0
> > + */
> > +int ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
> > +			   const struct ffa_partition_uuid *uuid2)
> 
> Would it make sense to use the bool type instead?
> 
> > +{
> > +	if (!uuid1 || !uuid2)
> > +		return 0;
> > +
> > +	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
> > +}
> > +
> > +/**
> > + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> > + *							and saves it in the private structure
> > + * @count: The number of partitions queried
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + *
> > + * This function reads the partitions information
> > + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> > + * data structure.
> > + *
> > + * Return:
> > + *
> > + * The private data structure is updated with the partition(s) information
> > + * 0 is returned on success. Otherwise, failure
> > + */
> > +static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
> > +{
> > +	if (!count) {
> > +		ffa_err("no partition detected");
> > +		return -ENODATA;
> > +	}
> > +
> > +	ffa_info("Reading partitions data from the RX buffer");
> > +
> > +	if (!part_uuid) {
> > +		/*
> > +		 * querying information of all partitions
> > +		 */
> > +		u64 buf_bytes;
> > +		u64 data_bytes;
> > +		u32 desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +
> > +		data_bytes = count * sizeof(struct ffa_partition_desc);
> > +
> > +		buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> > +
> > +		if (data_bytes > buf_bytes) {
> > +			ffa_err("partitions data size exceeds the RX buffer size:");
> > +			ffa_err("    sizes in bytes: data %llu , RX buffer %llu ",
> > +				data_bytes,
> > +				buf_bytes);
> > +
> > +			return -ENOMEM;
> > +		}
> > +
> > +		ffa_priv_data->partitions.descs = devm_kmalloc(ffa_priv_data->dev, data_bytes,
> > +							       __GFP_ZERO);
> > +		if (!ffa_priv_data->partitions.descs) {
> > +			ffa_err("cannot  allocate partitions data buffer");
> > +			return -ENOMEM;
> > +		}
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> > +
> > +		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
> > +			ffa_priv_data->partitions.descs[desc_idx].info =
> > +				parts_info[desc_idx];
> > +
> > +			ffa_info("Partition ID %x : info cached",
> > +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> > +		}
> > +
> > +		ffa_priv_data->partitions.count = count;
> > +
> > +		ffa_info("%d partition(s) found and cached", count);
> > +
> > +	} else {
> > +		u32 rx_desc_idx, cached_desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +		u8 desc_found;
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> > +
> > +		/*
> > +		 * search for the SP IDs read from the RX buffer
> > +		 * in the already cached SPs.
> > +		 * Update the UUID when ID found.
> > +		 */
> > +		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
> > +			desc_found = 0;
> > +
> > +			/*
> > +			 * search the current ID in the cached partitions
> > +			 */
> > +			for (cached_desc_idx = 0;
> > +			     cached_desc_idx < ffa_priv_data->partitions.count;
> > +			     cached_desc_idx++) {
> > +				/*
> > +				 * save the UUID
> > +				 */
> > +				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
> > +				    parts_info[rx_desc_idx].id) {
> > +					ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
> > +						*part_uuid;
> > +
> > +					desc_found = 1;
> > +					break;
> > +				}
> > +			}
> > +
> > +			if (!desc_found)
> > +				return -ENODATA;
> > +		}
> > +	}
> > +
> > +	return  0;
> > +}
> > +
> > +/**
> > + * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
> > + *
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + * @pcount: Pointer to the number of partitions variable filled when querying
> > + *
> > + * This function executes the FFA_PARTITION_INFO_GET
> > + * to query the partitions data. Then, it calls ffa_read_partitions_info
> > + * to save the data in the private data structure.
> > + *
> > + * After reading the data the RX buffer is released using ffa_release_rx_buffer
> > + *
> > + * Return:
> > + *
> > + * When part_uuid is NULL, all partitions data are retrieved from secure world
> > + * When part_uuid is non NULL, data for partitions matching the given UUID are
> > + * retrieved and the number of partitions is returned
> > + * 0 is returned on success. Otherwise, failure
> > + */
> > +static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
> > +				     u32 *pcount)
> > +{
> > +	struct ffa_partition_uuid query_uuid = {0};
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	/*
> > +	 * If a UUID is specified. Information for one or more
> > +	 * partitions in the system is queried. Otherwise, information
> > +	 * for all installed partitions is queried
> > +	 */
> > +
> > +	if (part_uuid) {
> > +		if (!pcount)
> > +			return -EINVAL;
> > +
> > +		query_uuid = *part_uuid;
> > +	} else if (pcount) {
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
> > +			.a1 = query_uuid.a1,
> > +			.a2 = query_uuid.a2,
> > +			.a3 = query_uuid.a3,
> > +			.a4 = query_uuid.a4
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		int ret;
> > +
> > +		/*
> > +		 * res.a2 contains the count of partition information descriptors
> > +		 * populated in the RX buffer
> > +		 */
> > +		if (res.a2) {
> > +			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
> > +			if (ret) {
> > +				ffa_err("failed to read partition(s) data , error (%d)", ret);
> > +				ffa_release_rx_buffer();
> > +				return -EINVAL;
> > +			}
> > +		}
> > +
> > +		/*
> > +		 * return the SP count (when querying using a UUID)
> > +		 */
> > +		if (pcount)
> > +			*pcount = (u32)res.a2;
> > +
> > +		/*
> > +		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
> > +		 * is assigned to the consumer (u-boot). So, we need to give
> > +		 * the ownership back to the SPM or hypervisor
> > +		 */
> > +		ret = ffa_release_rx_buffer();
> > +
> > +		return ret;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
> > + *
> > + * The passed arguments:
> > + * Mode 1: When getting from the driver the number of
> > + *	secure partitions:
> > + *	@uuid_str: pointer to the UUID string
> > + *	@parts_size: pointer to the variable that contains the number of partitions
> > + *			 The variable will be set by the driver
> > + *	@buffer: NULL
> > + *
> > + * Mode 2: When requesting the driver to return the
> > + *	partitions information:
> > + *	@uuid_str: pointer to the UUID string
> > + *	@parts_size: pointer to the size of the SPs information buffer in bytes
> > + *	@buffer: pointer to SPs information buffer
> > + *		(allocated by the client).
> > + *		The buffer will be filled by the driver
> > + *
> > + * This function queries the secure partition data from
> > + * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
> > + * FF-A function to query the partition information from secure world.
> > + *
> > + * A client of the FF-A driver should know the UUID of the service it wants to
> > + * access. It should use the UUID to request the FF-A driver to provide the
> > + * partition(s) information of the service. The FF-A driver uses
> > + * PARTITION_INFO_GET to obtain this information. This is implemented through
> > + * ffa_get_partitions_info function.
> > + * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
> > + * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
> > + * They are not saved (already done). We only update the UUID in the cached area.
> > + * This assumes that partitions data does not change in the secure world.
> > + * Otherwise u-boot will have an outdated partition data. The benefit of caching
> > + * the information in the FF-A driver is to accommodate discovery after
> > + * ExitBootServices().
> > + *
> > + * When invoked through a client request, ffa_get_partitions_info should be
> > + * called twice. First call is to get from the driver the number of secure
> > + * partitions (SPs) associated to a particular UUID.
> > + * Then, the caller (client) allocates the buffer to host the SPs data and
> > + * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
> > + * buffer.
> > + *
> > + * To achieve the mechanism described above, ffa_get_partitions_info uses the
> > + * following functions:
> > + *		ffa_read_partitions_info
> > + *		ffa_query_partitions_info
> > + *
> > + * Return:
> > + *
> > + * @parts_size: When pointing to the number of partitions variable, the number is
> > + * set by the driver.
> > + * When pointing to the partitions information buffer size, the buffer will be
> > + * filled by the driver.
> > + *
> > + * On success 0 is returned. Otherwise, failure
> > + */
> > +static int ffa_get_partitions_info(const char *uuid_str,
> > +				   u32 *parts_size, struct ffa_partition_info *buffer)
> > +{
> > +	/*
> > +	 * fill_data:
> > +	 * 0: return the SP count
> > +	 * 1: fill SP data and return it to the caller
> > +	 * -1: undefined mode
> > +	 */
> > +	int fill_data = -1;
> > +	u32 desc_idx, client_desc_idx;
> > +	struct ffa_partition_uuid part_uuid = {0};
> > +	u32 client_desc_max_cnt;
> > +	u32 parts_found = 0;
> > +
> > +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
> > +		ffa_err("no partition installed");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!uuid_str) {
> > +		ffa_err("no UUID provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!parts_size) {
> > +		ffa_err("no size/count provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (be_uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
> > +		ffa_err("invalid UUID");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!buffer) {
> > +		/* Mode 1: getting the number of secure partitions */
> > +
> > +		fill_data = 0;
> > +
> > +		ffa_info("Preparing for checking partitions count");
> > +
> > +	} else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
> > +		   !(*parts_size % sizeof(struct ffa_partition_info))) {
> > +		/* Mode 2: retrieving the partitions information */
> > +
> > +		fill_data = 1;
> > +
> > +		client_desc_idx = 0;
> > +
> > +		/*
> > +		 * number of empty descriptors preallocated by the caller
> > +		 */
> > +		client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
> > +
> > +		ffa_info("Preparing for filling partitions info");
> > +
> > +	} else {
> > +		ffa_err("invalid function arguments provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_info("Searching partitions using the provided UUID");
> > +
> > +	/*
> > +	 * search in the cached partitions
> > +	 */
> > +	for (desc_idx = 0;
> > +	     desc_idx < ffa_priv_data->partitions.count;
> > +	     desc_idx++) {
> > +		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
> > +					   &part_uuid)) {
> > +			ffa_info("Partition ID %x matches the provided UUID",
> > +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> > +
> > +			parts_found++;
> > +
> > +			if (fill_data) {
> > +				/*
> > +				 * trying to fill the partition info in the input buffer
> > +				 */
> > +
> > +				if (client_desc_idx < client_desc_max_cnt) {
> > +					buffer[client_desc_idx++] =
> > +						ffa_priv_data->partitions.descs[desc_idx].info;
> > +					continue;
> > +				}
> > +
> > +				ffa_err("failed to fill the current descriptor client buffer full");
> > +				return -ENOBUFS;
> > +			}
> > +		}
> > +	}
> > +
> > +	if (!parts_found) {
> > +		int ret;
> > +
> > +		ffa_info("No partition found. Querying framework ...");
> > +
> > +		ret = ffa_query_partitions_info(&part_uuid, &parts_found);
> > +
> > +		if (ret == 0) {
> > +			if (!fill_data) {
> > +				*parts_size = parts_found;
> > +
> > +				ffa_info("Number of partition(s) found matching the UUID: %d",
> > +					 parts_found);
> > +			} else {
> > +				/*
> > +				 * If SPs data detected, they are already in the private data
> > +				 * structure, retry searching SP data again to return them
> > +				 *  to the caller
> > +				 */
> > +				if (parts_found)
> > +					ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
> > +				else
> > +					ret = -ENODATA;
> > +			}
> > +		}
> > +
> > +		return ret;
> > +	}
> > +
> > +	/* partition(s) found */
> > +	if (!fill_data)
> > +		*parts_size = parts_found;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_cache_partitions_info - Queries and saves all secure partitions data
> > + *
> > + * This function invokes FFA_PARTITION_INFO_GET FF-A
> > + * function to query from secure world all partitions information.
> > + *
> > + * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
> > + * All installed partitions information are returned. We cache them in the
> > + * resident private data structure and we keep the UUID field empty
> > + * (in FF-A 1.0 UUID is not provided by the partition descriptor)
> > + *
> > + * This function is called at the device probing level.
> > + * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_cache_partitions_info(void)
> > +{
> > +	return ffa_query_partitions_info(NULL, NULL);
> > +}
> > +
> > +/**
> > + * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> > + * @dst_part_id: destination partition ID
> > + * @msg: pointer to the message data preallocated by the client (in/out)
> > + *
> > + * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * FF-A functions.
> > + *
> > + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> > + * The response from the secure partition is handled by reading the
> > + * FFA_MSG_SEND_DIRECT_RESP arguments.
> > + *
> > + * The maximum size of the data that can be exchanged is 40 bytes which is
> > + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> > + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
> > +		return -EINVAL;
> > +
> > +	/* No partition installed */
> > +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
> > +		return -ENODEV;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ),
> > +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
> > +				PREP_PART_ENDPOINT_ID(dst_part_id),
> > +			.a2 = 0,
> > +			.a3 = msg->data0,
> > +			.a4 = msg->data1,
> > +			.a5 = msg->data2,
> > +			.a6 = msg->data3,
> > +			.a7 = msg->data4,
> > +			}, &res);
> > +
> > +	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
> > +		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RUN),
> > +			.a1 = res.a1
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		/* Message sent with no response */
> > +		return 0;
> > +	}
> > +
> > +	if (res.a0 == FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP)) {
> > +		/*
> > +		 * Message sent with response
> > +		 * extract the return data
> > +		 */
> > +		msg->data0 = res.a3;
> > +		msg->data1 = res.a4;
> > +		msg->data2 = res.a5;
> > +		msg->data3 = res.a6;
> > +		msg->data4 = res.a7;
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * __arm_ffa_fn_smc - 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 low level SMC assembly function
> > + *
> > + * Return: void
> > + */
> > +void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
> > +{
> > +	arm_smccc_1_2_smc(&args, res);
> > +}
> > +
> > +/**
> > + * ffa_set_smc_conduit - Set the SMC conduit
> > + *
> > + * This function selects the SMC conduit by setting the driver invoke function
> > + * to SMC assembly function
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_set_smc_conduit(void)
> > +{
> > +	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
> > +
> > +	if (!ffa_priv_data->invoke_ffa_fn) {
> > +		ffa_err("failure to set the invoke function");
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_info("Conduit is SMC");
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_set_bus_ops - Set the bus driver operations
> > + *
> > + * Setting the driver callbacks.
> > + *
> > + */
> > +static void ffa_set_bus_ops(void)
> > +{
> > +	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
> > +	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
> > +	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
> > +}
> > +
> > +/**
> > + * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
> > + * @dev:	the arm_ffa device
> > + *
> > + * This function creates the main data structure embedding all the driver data.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_alloc_prvdata(struct udevice *dev)
> > +{
> > +	if (!dev) {
> > +		ffa_err("no udevice found");
> > +		return -ENODEV;
> > +	}
> > +
> > +	/* The device is registered with the DM. Let's create the driver main data structure*/
> > +
> > +	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
> > +	if (!ffa_priv_data) {
> > +		ffa_err("can not allocate the driver main data structure");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	ffa_priv_data->dev = dev;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_probe - The driver probe function
> > + * @dev:	the arm_ffa device
> > + *
> > + * Probing is done at boot time and triggered by the uclass device discovery.
> > + * At probe level the following actions are done:
> > + *	- setting the conduit
> > + *	- querying the FF-A framework version
> > + *	- querying from secure world the u-boot endpoint ID
> > + *	- querying from secure world the supported features of FFA_RXTX_MAP
> > + *	- mapping the RX/TX buffers
> > + *	- querying from secure world all the partitions information
> > + *
> > + * All data queried from secure world is saved in the resident private data structure.
> > + *
> > + * The probe will fail if either FF-A framework is not detected or the
> > + * FF-A requests are not behaving correctly. This ensures that the
> > + * driver is not installed and its operations are not exported to the clients.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_probe(struct udevice *dev)
> > +{
> > +	int ret;
> > +
> > +	ret = ffa_alloc_prvdata(dev);
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ffa_set_bus_ops();
> > +
> > +	ret = ffa_set_smc_conduit();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_version();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_endpoint_id();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_rxtx_map_features();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_map_rxtx_buffers();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_cache_partitions_info();
> 
> I've asked this before, but never got an answer:
> Why are we saving all the found partitions in a cache? It seems that
> FFA_PARTITION_INFO_GET could be called each time when needed instead
> without any noticeable overhead. Or is the result cached for some other
> reason?

I already replied here [1]. Please have a look.

[1]: https://lore.kernel.org/all/20221014102849.GA14576@e121910.cambridge.arm.com/

> 
> Cheers,
> Jens
> 
> > +	if (ret != 0) {
> > +		ffa_free_rxtx_buffers();
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_remove - The driver remove function
> > + * @dev:	the arm_ffa device
> > + * When the device is about to be removed ,  unmap the RX/TX buffers and free the memory
> > + * Return:
> > + *
> > + * 0 on success.
> > + */
> > +static int ffa_remove(struct udevice *dev)
> > +{
> > +	ffa_info("removing the device");
> > +
> > +	ffa_unmap_rxtx_buffers();
> > +
> > +	if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
> > +		ffa_free_rxtx_buffers();
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_unbind - The driver unbind function
> > + * @dev:	the arm_ffa device
> > + * After the device is removed and memory freed the device is unbound
> > + * Return:
> > + *
> > + * 0 on success.
> > + */
> > +static int ffa_unbind(struct udevice *dev)
> > +{
> > +	ffa_info("unbinding the device , private data already released");
> > +
> > +	ffa_priv_data = NULL;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_bus_ops_get - bus driver operations getter
> > + *
> > + * Return:
> > + * This function returns a pointer to the driver operations structure
> > + */
> > +const struct ffa_bus_ops *ffa_bus_ops_get(void)
> > +{
> > +	return &ffa_priv_data->ffa_ops;
> > +}
> > +
> > +/**
> > + * ffa_bus_prvdata_get - bus driver private data getter
> > + *
> > + * Return:
> > + * This function returns a pointer to the main private data structure
> > + */
> > +struct ffa_prvdata **ffa_bus_prvdata_get(void)
> > +{
> > +	return &ffa_priv_data;
> > +}
> > +
> > +/**
> > + * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
> > + *
> > + * 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 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.
> > + * All FF-A clients should use the arm_ffa device to use the FF-A transport.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_bus_discover(void)
> > +{
> > +	int ret = 0;
> > +
> > +	if (!ffa_priv_data)
> > +		ret = ffa_device_get();
> > +
> > +	return ret;
> > +}
> > +
> > +/**
> > + * Declaring the arm_ffa driver under UCLASS_FFA
> > + */
> > +
> > +U_BOOT_DRIVER(arm_ffa) = {
> > +	.name		= FFA_DRV_NAME,
> > +	.id		= UCLASS_FFA,
> > +	.probe		= ffa_probe,
> > +	.remove		= ffa_remove,
> > +	.unbind		= ffa_unbind,
> > +};
> > diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> > new file mode 100644
> > index 0000000000..d146e7b328
> > --- /dev/null
> > +++ b/include/arm_ffa.h
> > @@ -0,0 +1,93 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_H
> > +#define __ARM_FFA_H
> > +
> > +#include <linux/printk.h>
> > +
> > +/*
> > + * This header is public. It can be used by clients to access
> > + * data structures and definitions they need
> > + */
> > +
> > +/*
> > + * Macros for displaying logs
> > + */
> > +
> > +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +
> > +/*
> > + * struct ffa_partition_info - Partition information descriptor
> > + * @id:	Partition ID
> > + * @exec_ctxt:	Execution context count
> > + * @properties:	Partition properties
> > + *
> > + * Data structure containing information about partitions instantiated in the system
> > + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> > + */
> > +struct  __packed ffa_partition_info {
> > +	u16 id;
> > +	u16 exec_ctxt;
> > +/* partition supports receipt of direct requests */
> > +#define FFA_PARTITION_DIRECT_RECV	BIT(0)
> > +/* partition can send direct requests. */
> > +#define FFA_PARTITION_DIRECT_SEND	BIT(1)
> > +/* partition can send and receive indirect messages. */
> > +#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
> > +	u32 properties;
> > +};
> > +
> > +/*
> > + * struct ffa_send_direct_data - Data structure hosting the data
> > + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * @data0-4:	Data read/written from/to x3-x7 registers
> > + *
> > + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> > + * or read from FFA_MSG_SEND_DIRECT_RESP
> > + */
> > +
> > +/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
> > +struct __packed ffa_send_direct_data {
> > +	unsigned long data0; /* w3/x3 */
> > +	unsigned long data1; /* w4/x4 */
> > +	unsigned long data2; /* w5/x5 */
> > +	unsigned long data3; /* w6/x6 */
> > +	unsigned long data4; /* w7/x7 */
> > +};
> > +
> > +/**
> > + * struct ffa_bus_ops - The driver operations structure
> > + * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
> > + * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
> > + * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
> > + *
> > + * The data structure providing all the operations supported by the driver.
> > + * This structure is EFI runtime resident.
> > + */
> > +struct ffa_bus_ops {
> > +	int (*partition_info_get)(const char *uuid_str,
> > +				  u32 *parts_size, struct ffa_partition_info *buffer);
> > +	int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg);
> > +	int (*rxtx_unmap)(void);
> > +};
> > +
> > +/**
> > + * The device driver and the Uclass driver public functions
> > + */
> > +
> > +/**
> > + * ffa_bus_ops_get - driver operations getter
> > + */
> > +const struct ffa_bus_ops *ffa_bus_ops_get(void);
> > +
> > +/**
> > + * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
> > + */
> > +int ffa_bus_discover(void);
> > +
> > +#endif
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index a432e43871..5dd698b7a9 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -4,6 +4,9 @@
> >   *
> >   * (C) Copyright 2012
> >   * Pavel Herrmann <morpheus.ibis@gmail.com>
> > + *
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  
> >  #ifndef _DM_UCLASS_ID_H
> > @@ -55,6 +58,7 @@ enum uclass_id {
> >  	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
> >  	UCLASS_ETH,		/* Ethernet device */
> >  	UCLASS_ETH_PHY,		/* Ethernet PHY device */
> > +	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
> >  	UCLASS_FIRMWARE,	/* Firmware */
> >  	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
> >  	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
> > -- 
> > 2.17.1
> > 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v7 00/10] introduce Arm FF-A support
  2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                       ` (10 preceding siblings ...)
  2022-10-13 12:07                                     ` [PATCH v6 00/10] introduce Arm FF-A support Ilias Apalodimas
@ 2022-11-07 19:20                                     ` Abdellatif El Khlifi
  2022-11-07 19:20                                       ` [PATCH v7 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                         ` (11 more replies)
  11 siblings, 12 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-07 19:20 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong,
	Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [7].

FF-A describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World. These interfaces enable a pair of
software sandboxes to communicate with each other. A sandbox aka partition could
be a VM in the Normal or Secure world, an application in S-EL0, or a
Trusted OS in S-EL1.

The FF-A transport is implemented as a data bus and a core driver is provided.

This implementation of the specification provides support for Aarch64.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

    - Discover the presence of secure partitions (SPs) of interest
    - Access an SP's service through communication protocols
      e.g. EFI MM communication protocol

The FF-A support provides the following features:

    - Being generic by design and can be used by any Arm 64-bit platform
    - The FF-A core driver
    - The FF-A bus is discoverable on demand at runtime
    - The driver provides driver operations to be used by clients to access the FF-A bus
    - FF-A driver can be compiled and used without EFI
    - Support for SMCCCv1.2 x0-x17 registers
    - Support for SMC32 calling convention
    - Support for 32-bit and 64-bit FF-A direct messaging
    - A new command called armffa is provided as an example of how to access the
      FF-A bus
    - An FF-A Sandbox driver is provided with test cases
    - Support for FF-A MM communication (compatible with EFI boot time)
    - Enabling FF-A and MM communication in Corstone1000 platform

For more details about the FF-A core driver please refer to [8].

Please find at [9] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of the major changes:
===========================

v7:

* add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v6: [6]

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
[7]: https://developer.arm.com/documentation/den0077/latest/
[8]: doc/arch/arm64.ffa.rst
[9]: example of boot logs when enabling FF-A

```
U-Boot 2022.07 (Jul 11 2022 - 13:42:58 +0000) corstone1000 aarch64 
...
[FFA] Conduit is SMC
[FFA] FF-A driver 1.0
FF-A framework 1.0
[FFA] Versions are compatible 
[FFA] endpoint ID is 0
[FFA] Using 1 4KB page(s) for RX/TX buffers size
[FFA] RX buffer at virtual address 0xfdf18000
[FFA] TX buffer at virtual address 0xfdf1a000
[FFA] RX/TX buffers mapped
[FFA] Reading partitions data from the RX buffer
[FFA] Partition ID 8001 : info cached
[FFA] Partition ID 8002 : info cached
[FFA] Partition ID 8003 : info cached
[FFA] 3 partition(s) found and cached
[FFA] Preparing for checking partitions count
[FFA] Searching partitions using the provided UUID
[FFA] No partition found. Querying framework ...
[FFA] Reading partitions data from the RX buffer
[FFA] Number of partition(s) found matching the UUID: 1
EFI: Pre-allocating 1 partition(s) info structures
[FFA] Preparing for filling partitions info
[FFA] Searching partitions using the provided UUID
[FFA] Partition ID 8003 matches the provided UUID
EFI: MM partition ID 0x8003
...
Booting /MemoryMapped(0x0,0x88200000,0xf00000)
EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from configuration table
EFI stub: Exiting boot services...
[FFA] Freeing RX/TX buffers
Booting Linux on physical CPU 0x0000000000 [0x410fd040]
Linux version 5.19.9-yocto-standard (oe-user@oe-host)
(aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld
(GNU Binutils) 2.39.0.20220819) #1 SMP PREEMPT Wed Sep 21 20:11:18 UTC 2022
```

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>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Vishnu Banavath <vishnu.banavath@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (10):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce uuid_str_to_le_bin function
  arm_ffa: introduce Arm FF-A low-level driver
  arm_ffa: efi: unmap RX/TX buffers
  arm_ffa: introduce armffa command
  arm_ffa: introduce the FF-A Sandbox driver
  arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   11 +
 arch/arm/cpu/armv8/smccc-call.S               |   53 +
 arch/arm/lib/asm-offsets.c                    |   14 +
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    2 +
 cmd/armffa.c                                  |  239 +++
 configs/corstone1000_defconfig                |    4 +
 configs/sandbox64_defconfig                   |    2 +
 configs/sandbox_defconfig                     |    2 +
 doc/arch/arm64.ffa.rst                        |  218 +++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox.rst                          |    1 +
 drivers/Kconfig                               |    2 +
 drivers/Makefile                              |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   36 +
 drivers/firmware/arm-ffa/Makefile             |    7 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     |   16 +
 drivers/firmware/arm-ffa/arm_ffa_prv.h        |  210 +++
 drivers/firmware/arm-ffa/core.c               | 1324 +++++++++++++++++
 drivers/firmware/arm-ffa/sandbox.c            |  659 ++++++++
 .../firmware/arm-ffa/sandbox_arm_ffa_prv.h    |  144 ++
 include/arm_ffa.h                             |   93 ++
 include/configs/corstone1000.h                |    9 +
 include/dm/uclass-id.h                        |    4 +
 include/linux/arm-smccc.h                     |   43 +
 include/mm_communication.h                    |    5 +
 include/sandbox_arm_ffa.h                     |   91 ++
 include/uuid.h                                |    8 +
 lib/efi_loader/Kconfig                        |   14 +-
 lib/efi_loader/efi_boottime.c                 |   13 +
 lib/efi_loader/efi_variable_tee.c             |  269 +++-
 lib/uuid.c                                    |   46 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   40 +
 test/dm/Makefile                              |    2 +
 test/dm/ffa.c                                 |  394 +++++
 36 files changed, 3983 insertions(+), 6 deletions(-)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/firmware/arm-ffa/core.c
 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/arm_ffa.h
 create mode 100644 include/sandbox_arm_ffa.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v7 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
@ 2022-11-07 19:20                                       ` Abdellatif El Khlifi
  2022-11-07 19:20                                       ` [PATCH v7 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
                                                         ` (10 subsequent siblings)
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-07 19:20 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>

---

Changelog:
===============

v7:

* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

arch/arm/cpu/armv8/smccc-call.S | 53 +++++++++++++++++++++++++++++++++
 arch/arm/lib/asm-offsets.c      | 14 +++++++++
 include/linux/arm-smccc.h       | 43 ++++++++++++++++++++++++++
 3 files changed, 110 insertions(+)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..ec6f299bc9 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
@@ -45,3 +47,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 22fd541f9a..db6d7ed234 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,9 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -117,6 +120,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#ifdef CONFIG_ARM64
+	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..9105031d55 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +72,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v7 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
  2022-11-07 19:20                                       ` [PATCH v7 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2022-11-07 19:20                                       ` Abdellatif El Khlifi
  2022-11-08 13:47                                         ` Ilias Apalodimas
  2022-11-11 17:02                                         ` Anders Dellien
  2022-11-07 19:20                                       ` [PATCH v7 03/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
                                                         ` (9 subsequent siblings)
  11 siblings, 2 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-07 19:20 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

convert UUID string to little endian binary data

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>

---

Changelog:
===============

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

include/uuid.h |  8 ++++++++
 lib/uuid.c     | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..293a8eb0a5 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,8 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +46,10 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin - Converts a UUID string to little endian binary data
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 465e1ac38f..cde5ae2bb7 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -346,6 +348,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16;
+	u32 tmp32;
+	u64 tmp64;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+	memcpy(uuid_bin, &tmp32, 4);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	tmp64 = cpu_to_le64(hextoul(uuid_str + 24, NULL));
+	memcpy(uuid_bin + 10, (char *)&tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v7 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
  2022-11-07 19:20                                       ` [PATCH v7 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2022-11-07 19:20                                       ` [PATCH v7 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2022-11-07 19:20                                       ` Abdellatif El Khlifi
  2022-11-09 11:51                                         ` Jens Wiklander
  2022-11-07 19:20                                       ` [PATCH v7 04/10] arm_ffa: efi: unmap RX/TX buffers Abdellatif El Khlifi
                                                         ` (8 subsequent siblings)
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-07 19:20 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

In U-Boot FF-A design, FF-A is considered as a discoverable bus.
The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- partition_info_get
- sync_send_receive
- rxtx_unmap

For more details please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

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>

---

Changelog:
===============

v7:

* add support for 32-bit direct messaging
* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* improve the declaration of error handling mapping
* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the U-Boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the U-Boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

MAINTAINERS                               |    7 +
 doc/arch/arm64.ffa.rst                    |  218 ++++
 doc/arch/index.rst                        |    1 +
 drivers/Kconfig                           |    2 +
 drivers/Makefile                          |    1 +
 drivers/firmware/arm-ffa/Kconfig          |   30 +
 drivers/firmware/arm-ffa/Makefile         |    6 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c |   16 +
 drivers/firmware/arm-ffa/arm_ffa_prv.h    |  205 ++++
 drivers/firmware/arm-ffa/core.c           | 1310 +++++++++++++++++++++
 include/arm_ffa.h                         |   93 ++
 include/dm/uclass-id.h                    |    4 +
 12 files changed, 1893 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/firmware/arm-ffa/core.c
 create mode 100644 include/arm_ffa.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 1cf99c1393..450b5725ce 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -263,6 +263,13 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	doc/arch/arm64.ffa.rst
+F:	drivers/firmware/arm-ffa/
+F:	include/arm_ffa.h
+
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..dfcec82e45
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,218 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Driver
+===============
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software sandboxes to
+communicate with each other. A sandbox aka partition could
+be a VM in the Normal or Secure world, an application in S-EL0, or a
+Trusted OS in S-EL1.
+
+This FF-A driver implements the interfaces to communicate with partitions in
+the Secure world aka Secure partitions (SPs).
+
+The driver specifically focuses on communicating with SPs that isolate portions
+of EFI runtime services that must run in a protected environment which is
+inaccessible by the Host OS or Hypervisor. Examples of such services are
+set/get variables.
+
+FF-A driver uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+At this stage of development the FF-A driver supports EFI boot time only.
+
+Runtime support will be added in future developments.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the driver relies on FF-A specification v1.0
+and uses SMC32 calling convention which means using the first 32-bit data of the
+Xn registers.
+
+At this stage we only need the FF-A v1.0 features.
+
+The driver has been tested with OP-TEE which supports SMC32 calling convention.
+
+For more details please refer to the FF-A v1.0 spec:
+https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
+
+For more details please refer to the SMC Calling Convention v1.2 spec:
+https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+CONFIG_ARM_FFA_TRANSPORT
+    Enables the FF-A bus driver. Turn this on if you want to use FF-A
+    communication.
+
+CONFIG_SANDBOX_FFA
+    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
+    Sandbox and provides functional tests for FF-A.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction
+is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-Boot FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs in the driver.
+
+FF-A bus discovery in U-Boot
+-------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is discovered on
+demand by the clients (users).
+
+Clients can discover the FF-A bus using ffa_bus_discover() API which triggers the
+discovery process.
+
+ffa_bus_discover() creates, binds and probes the arm_ffa device using
+device_{bind, probe} APIs.
+
+The discovery process consists in communicating with secure world (or hypervisor)
+and querying specific data.
+
+The discovery process takes place during the arm_ffa device probing which is
+handled by ffa_probe().
+
+The FF-A bus discovery is successful and the bus is ready for use when these
+operations succeed:
+
+- querying the FF-A framework version
+- querying from secure world the U-Boot endpoint ID
+- querying from secure world the RX/TX mapping  features
+- mapping the RX/TX buffers
+- querying from secure world all the partitions information
+
+Discovery failure results in a probing failure and the arm_ffa device is
+destroyed.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must:
+
+- Query SPs in EFI boot time mode using the service UUID.
+- Unmap RX/TX buffers before EFI runtime mode starts.
+
+The RX/TX buffers are only available at EFI boot time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped by the user before EFI runtime mode
+starts. The driver provides a bus operation for that: rxtx_unmap()
+
+If  RX/TX buffers created by U-Boot are not unmapped and by
+consequence becoming available at EFI runtime, secure world will get confused
+about RX/TX buffers ownership (U-Boot vs kernel).
+
+When invoking FF-A direct messaging, clients should specify which ABI protocol
+they want to use (32-bit vs 64-bit). Selecting the protocol means using
+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
+The calling convention stays the same: SMC32.
+
+The bus driver layer
+------------------------------
+
+The driver comes on top of the SMCCC layer and is implemented in
+drivers/firmware/arm-ffa/core.c
+
+The driver provides the following features:
+
+- Support for the 32-bit version of the following ABIs:
+
+FFA_VERSION
+FFA_ID_GET
+FFA_FEATURES
+FFA_PARTITION_INFO_GET
+FFA_RXTX_UNMAP
+FFA_RX_RELEASE
+FFA_RUN
+FFA_ERROR
+FFA_SUCCESS
+FFA_INTERRUPT
+FFA_MSG_SEND_DIRECT_REQ
+FFA_MSG_SEND_DIRECT_RESP
+
+- Support for the 64-bit version of the following ABIs:
+
+FFA_RXTX_MAP
+FFA_MSG_SEND_DIRECT_REQ
+FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, the driver takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- The driver provides callbacks to be used by clients to access the FF-A bus:
+
+partition_info_get
+sync_send_receive
+rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+Using armffa command
+-----------------------------------
+
+armffa is an implementation defined command showcasing how to use the FF-A driver and how to invoke
+its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus
+interfaces.
+
+Usage:
+
+armffa <sub-command> <arguments>
+
+sub-commands:
+
+        getpart <partition UUID>
+
+            lists the partition(s) info
+
+        ping <partition ID>
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays the arm_ffa device info
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index 792d9182c3..8d1ab0ad4e 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 8b6fead351..b06b1ae481 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
 
 source "drivers/adc/Kconfig"
 
+source "drivers/firmware/arm-ffa/Kconfig"
+
 source "drivers/ata/Kconfig"
 
 source "drivers/axi/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index a1700c819d..b86c1d2a42 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -111,6 +111,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..e4914b9bc7
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,30 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  This driver is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  This FF-A driver takes care of all the interactions between Normal world
+	  and Secure World.
+
+	  For more details about the FF-A driver, please refer to doc/arch/arm64.ffa.rst
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..043a8915be
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2022
+# Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com.
+
+obj-y += arm-ffa-uclass.o core.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..7d9695d289
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+UCLASS_DRIVER(ffa) = {
+	.name		= "ffa",
+	.id		= UCLASS_FFA,
+};
diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
new file mode 100644
index 0000000000..ad7430ada9
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <arm_ffa.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/arm-smccc.h>
+
+/*
+ * This header is private. It is exclusively used by the FF-A driver
+ */
+
+/* FF-A core driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* FF-A driver version definitions */
+
+#define MAJOR_VERSION_MASK		GENMASK(30, 16)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/*
+ * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
+ */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR					= 0x60,
+	FFA_SUCCESS					= 0x61,
+	FFA_INTERRUPT				= 0x62,
+	FFA_VERSION					= 0x63,
+	FFA_FEATURES				= 0x64,
+	FFA_RX_RELEASE				= 0x65,
+	FFA_RXTX_MAP				= 0x66,
+	FFA_RXTX_UNMAP			= 0x67,
+	FFA_PARTITION_INFO_GET		= 0x68,
+	FFA_ID_GET					= 0x69,
+	FFA_RUN						= 0x6D,
+	FFA_MSG_SEND_DIRECT_REQ	= 0x6F,
+	FFA_MSG_SEND_DIRECT_RESP	= 0x70,
+
+	/* to be updated when adding new FFA IDs */
+	FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
+	FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
+};
+
+enum ffa_abi_errcode {
+	NOT_SUPPORTED = 1,
+	INVALID_PARAMETERS,
+	NO_MEMORY,
+	BUSY,
+	INTERRUPTED,
+	DENIED,
+	RETRY,
+	ABORTED,
+	MAX_NUMBER_FFA_ERR
+};
+
+/* container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#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
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Data structure hosting the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	u64 rxbuf; /* virtual address */
+	u64 txbuf; /* virtual address */
+	size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * This data structure contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* virtual address */
+};
+
+/**
+ * struct ffa_prvdata - the driver private data structure
+ *
+ * @dev:	The arm_ffa device under u-boot driver model
+ * @ffa_ops:	The driver operations structure
+ * @fwk_version:	FF-A framework version
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ * @invoke_ffa_fn:	The function executing the FF-A function
+ *
+ * The driver data structure hosting all resident data.
+ */
+struct ffa_prvdata {
+	struct udevice *dev;
+	struct ffa_bus_ops ffa_ops;
+	u32 fwk_version;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+	invoke_ffa_fn_t invoke_ffa_fn;
+};
+
+/**
+ * ffa_device_get - create, bind and probe the arm_ffa device
+ */
+int ffa_device_get(void);
+
+/**
+ * ffa_bus_prvdata_get - bus driver private data getter
+ */
+struct ffa_prvdata **ffa_bus_prvdata_get(void);
+
+#endif
diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
new file mode 100644
index 0000000000..b955e5187b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/core.c
@@ -0,0 +1,1310 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include "arm_ffa_prv.h"
+#include <asm/global_data.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * The device private data structure containing all the
+ * data read from secure world
+ */
+struct ffa_prvdata *ffa_priv_data;
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	[NOT_SUPPORTED] = -EOPNOTSUPP,
+	[INVALID_PARAMETERS] = -EINVAL,
+	[NO_MEMORY] = -ENOMEM,
+	[BUSY] = -EBUSY,
+	[INTERRUPTED] = -EINTR,
+	[DENIED] = -EACCES,
+	[RETRY] = -EAGAIN,
+	[ABORTED] = -ECANCELED,
+};
+
+struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			[NO_MEMORY] =
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			[BUSY] =
+			"BUSY: RX buffer of the caller is not free",
+			[DENIED] =
+			"DENIED: Callee is not in a state to handle this request",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+			{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+			{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			[DENIED] =
+			"DENIED: Caller did not have ownership of the RX buffer",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+			{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			[NO_MEMORY] =
+			"NO_MEMORY: Not enough memory",
+			[DENIED] =
+			"DENIED: Buffer pair already registered",
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This function maps the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This function maps the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/*
+ * Driver core functions
+ */
+
+/**
+ * ffa_remove_device - removes the arm_ffa device
+ * @dev:	the device to be removed
+ *
+ * This function makes sure the arm_ffa device is removed
+ * No need to free the kmalloced data when the device is destroyed.
+ * It's automatically done by devm management by
+ * device_remove() -> device_free() -> devres_release_probe().
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_remove_device(struct udevice *dev)
+{
+	int ret;
+
+	if (!dev) {
+		ffa_err("no udevice found");
+		return -ENODEV;
+	}
+
+	ret = device_remove(dev, DM_REMOVE_NORMAL);
+	if (ret) {
+		ffa_err("unable to remove. err:%d\n", ret);
+		return ret;
+	}
+
+	ffa_info("device removed and freed");
+
+	ret = device_unbind(dev);
+	if (ret) {
+		ffa_err("unable to unbind. err:%d\n", ret);
+		return ret;
+	}
+
+	ffa_info("device unbound");
+
+	return 0;
+}
+
+/**
+ * ffa_device_get - create, bind and probe the arm_ffa device
+ *
+ * This function makes sure the arm_ffa device is
+ * created, bound to this driver, probed and ready to use.
+ * Arm FF-A transport is implemented through a single u-boot
+ * device managing the FF-A bus (arm_ffa).
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_device_get(void)
+{
+	int ret;
+	struct udevice *dev = NULL;
+
+	ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
+			  &dev);
+	if (ret)
+		return ret;
+
+	/* The FF-A bus discovery succeeds when probing is successful */
+	ret = device_probe(dev);
+	if (ret) {
+		ffa_err("arm_ffa device probing failed");
+		ffa_remove_device(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_version - FFA_VERSION handler function
+ *
+ * This function implements FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_version(void)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
+		ffa_info("Versions are compatible ");
+
+		ffa_priv_data->fwk_version = res.a0;
+
+		return 0;
+	}
+
+	ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id - FFA_ID_GET handler function
+ *
+ * This function implements FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		ffa_info("endpoint ID is %u", ffa_priv_data->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * This function sets the minimum number of pages
+ *  in each of the RX/TX buffers in the private data structure
+ *
+ * Return:
+ *
+ * buf_4k_pages points to the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
+{
+	if (!ffa_priv_data)
+		return -EINVAL;
+
+	switch (prop_field) {
+	case RXTX_4K:
+		ffa_priv_data->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		ffa_priv_data->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		ffa_priv_data->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		ffa_err("RX/TX buffer size not supported");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ *
+ * This function implements FFA_FEATURES FF-A function
+ * to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt(res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers - frees the RX/TX buffers
+ *
+ * This  function  frees the RX/TX buffers
+ *
+ */
+static void ffa_free_rxtx_buffers(void)
+{
+	ffa_info("Freeing RX/TX buffers");
+
+	if (ffa_priv_data->pair.rxbuf) {
+		free((void *)ffa_priv_data->pair.rxbuf);
+		ffa_priv_data->pair.rxbuf = 0;
+	}
+
+	if (ffa_priv_data->pair.txbuf) {
+		free((void *)ffa_priv_data->pair.txbuf);
+		ffa_priv_data->pair.txbuf = 0;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
+ *
+ * This function is used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(void)
+{
+	u64 bytes;
+
+	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
+		 ffa_priv_data->pair.rxtx_min_pages);
+
+	bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 */
+
+	ffa_priv_data->pair.rxbuf = (u64)memalign(bytes, bytes);
+	if (!ffa_priv_data->pair.rxbuf) {
+		ffa_err("failure to allocate RX buffer");
+		return -ENOBUFS;
+	}
+
+	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
+
+	ffa_priv_data->pair.txbuf = (u64)memalign(bytes, bytes);
+	if (!ffa_priv_data->pair.txbuf) {
+		free((void *)ffa_priv_data->pair.rxbuf);
+		ffa_priv_data->pair.rxbuf = 0;
+		ffa_err("failure to allocate the TX buffer");
+		return -ENOBUFS;
+	}
+
+	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
+
+	/*
+	 * make sure the buffers are cleared before use
+	 */
+	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
+	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
+ *
+ * This function implements FFA_RXTX_MAP FF-A function
+ * to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers(void)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ret = ffa_alloc_rxtx_buffers();
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 * no need to convert from virtual to physical
+	 */
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = ffa_priv_data->pair.txbuf,
+			.a2 = ffa_priv_data->pair.rxbuf,
+			.a3 = ffa_priv_data->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_info("RX/TX buffers mapped");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers();
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_unmap_rxtx_buffers(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers();
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
+ *
+ * This function invokes FFA_RX_RELEASE FF-A function
+ * to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical - checks whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * This function is used by ffa_read_partitions_info to search
+ * for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+			    const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
+ *							and saves it in the private structure
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * This function reads the partitions information
+ * returned by the FFA_PARTITION_INFO_GET and saves it in the private
+ * data structure.
+ *
+ * Return:
+ *
+ * The private data structure is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
+{
+	if (!count) {
+		ffa_err("no partition detected");
+		return -ENODATA;
+	}
+
+	ffa_info("Reading partitions data from the RX buffer");
+
+	if (!part_uuid) {
+		/*
+		 * querying information of all partitions
+		 */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			ffa_err("partitions data size exceeds the RX buffer size:");
+			ffa_err("    sizes in bytes: data %llu , RX buffer %llu ",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		ffa_priv_data->partitions.descs = devm_kmalloc(ffa_priv_data->dev, data_bytes,
+							       __GFP_ZERO);
+		if (!ffa_priv_data->partitions.descs) {
+			ffa_err("cannot  allocate partitions data buffer");
+			return -ENOMEM;
+		}
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			ffa_priv_data->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			ffa_info("Partition ID %x : info cached",
+				 ffa_priv_data->partitions.descs[desc_idx].info.id);
+		}
+
+		ffa_priv_data->partitions.count = count;
+
+		ffa_info("%d partition(s) found and cached", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
+
+		/*
+		 * search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/*
+			 * search the current ID in the cached partitions
+			 */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < ffa_priv_data->partitions.count;
+			     cached_desc_idx++) {
+				/*
+				 * save the UUID
+				 */
+				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
+ *
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * This function executes the FFA_PARTITION_INFO_GET
+ * to query the partitions data. Then, it calls ffa_read_partitions_info
+ * to save the data in the private data structure.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
+			if (ret) {
+				ffa_err("failed to read partition(s) data , error (%d)", ret);
+				ffa_release_rx_buffer();
+				return -EINVAL;
+			}
+		}
+
+		/*
+		 * return the SP count (when querying using a UUID)
+		 */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer();
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
+ *
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@uuid_str: pointer to the UUID string
+ *	@parts_size: pointer to the variable that contains the number of partitions
+ *			 The variable will be set by the driver
+ *	@buffer: NULL
+ *
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@uuid_str: pointer to the UUID string
+ *	@parts_size: pointer to the size of the SPs information buffer in bytes
+ *	@buffer: pointer to SPs information buffer
+ *		(allocated by the client).
+ *		The buffer will be filled by the driver
+ *
+ * This function queries the secure partition data from
+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * When invoked through a client request, ffa_get_partitions_info should be
+ * called twice. First call is to get from the driver the number of secure
+ * partitions (SPs) associated to a particular UUID.
+ * Then, the caller (client) allocates the buffer to host the SPs data and
+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
+ * buffer.
+ *
+ * To achieve the mechanism described above, ffa_get_partitions_info uses the
+ * following functions:
+ *		ffa_read_partitions_info
+ *		ffa_query_partitions_info
+ *
+ * Return:
+ *
+ * @parts_size: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer size, the buffer will be
+ * filled by the driver.
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+static int ffa_get_partitions_info(const char *uuid_str,
+				   u32 *parts_size, struct ffa_partition_info *buffer)
+{
+	/*
+	 * fill_data:
+	 * 0: return the SP count
+	 * 1: fill SP data and return it to the caller
+	 * -1: undefined mode
+	 */
+	int fill_data = -1;
+	u32 desc_idx, client_desc_idx;
+	struct ffa_partition_uuid part_uuid = {0};
+	u32 client_desc_max_cnt;
+	u32 parts_found = 0;
+
+	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
+		ffa_err("no partition installed");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		ffa_err("no UUID provided");
+		return -EINVAL;
+	}
+
+	if (!parts_size) {
+		ffa_err("no size/count provided");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		ffa_err("invalid UUID");
+		return -EINVAL;
+	}
+
+	if (!buffer) {
+		/* Mode 1: getting the number of secure partitions */
+
+		fill_data = 0;
+
+		ffa_info("Preparing for checking partitions count");
+
+	} else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
+		   !(*parts_size % sizeof(struct ffa_partition_info))) {
+		/* Mode 2: retrieving the partitions information */
+
+		fill_data = 1;
+
+		client_desc_idx = 0;
+
+		/*
+		 * number of empty descriptors preallocated by the caller
+		 */
+		client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
+
+		ffa_info("Preparing for filling partitions info");
+
+	} else {
+		ffa_err("invalid function arguments provided");
+		return -EINVAL;
+	}
+
+	ffa_info("Searching partitions using the provided UUID");
+
+	/*
+	 * search in the cached partitions
+	 */
+	for (desc_idx = 0;
+	     desc_idx < ffa_priv_data->partitions.count;
+	     desc_idx++) {
+		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
+					   &part_uuid)) {
+			ffa_info("Partition ID %x matches the provided UUID",
+				 ffa_priv_data->partitions.descs[desc_idx].info.id);
+
+			parts_found++;
+
+			if (fill_data) {
+				/*
+				 * trying to fill the partition info in the input buffer
+				 */
+
+				if (client_desc_idx < client_desc_max_cnt) {
+					buffer[client_desc_idx++] =
+						ffa_priv_data->partitions.descs[desc_idx].info;
+					continue;
+				}
+
+				ffa_err("failed to fill the current descriptor client buffer full");
+				return -ENOBUFS;
+			}
+		}
+	}
+
+	if (!parts_found) {
+		int ret;
+
+		ffa_info("No partition found. Querying framework ...");
+
+		ret = ffa_query_partitions_info(&part_uuid, &parts_found);
+
+		if (ret == 0) {
+			if (!fill_data) {
+				*parts_size = parts_found;
+
+				ffa_info("Number of partition(s) found matching the UUID: %d",
+					 parts_found);
+			} else {
+				/*
+				 * If SPs data detected, they are already in the private data
+				 * structure, retry searching SP data again to return them
+				 *  to the caller
+				 */
+				if (parts_found)
+					ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
+				else
+					ret = -ENODATA;
+			}
+		}
+
+		return ret;
+	}
+
+	/* partition(s) found */
+	if (!fill_data)
+		*parts_size = parts_found;
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info - Queries and saves all secure partitions data
+ *
+ * This function invokes FFA_PARTITION_INFO_GET FF-A
+ * function to query from secure world all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in the
+ * resident private data structure and we keep the UUID field empty
+ * (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * This function is called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(void)
+{
+	return ffa_query_partitions_info(NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u64 req_mode, resp_mode;
+
+	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
+		return -EINVAL;
+
+	/* No partition installed */
+	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
+		return -ENODEV;
+
+	if (is_smc64) {
+		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+	} else {
+		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
+	}
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = req_mode,
+			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == resp_mode) {
+		/*
+		 * Message sent with response
+		 * extract the return data
+		 */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * __arm_ffa_fn_smc - 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 low level SMC assembly function
+ *
+ * Return: void
+ */
+void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * ffa_set_smc_conduit - Set the SMC conduit
+ *
+ * This function selects the SMC conduit by setting the driver invoke function
+ * to SMC assembly function
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_smc_conduit(void)
+{
+	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
+
+	if (!ffa_priv_data->invoke_ffa_fn) {
+		ffa_err("failure to set the invoke function");
+		return -EINVAL;
+	}
+
+	ffa_info("Conduit is SMC");
+
+	return 0;
+}
+
+/**
+ * ffa_set_bus_ops - Set the bus driver operations
+ *
+ * Setting the driver callbacks.
+ *
+ */
+static void ffa_set_bus_ops(void)
+{
+	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
+	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
+	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
+}
+
+/**
+ * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
+ * @dev:	the arm_ffa device
+ *
+ * This function creates the main data structure embedding all the driver data.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_prvdata(struct udevice *dev)
+{
+	if (!dev) {
+		ffa_err("no udevice found");
+		return -ENODEV;
+	}
+
+	/* The device is registered with the DM. Let's create the driver main data structure*/
+
+	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
+	if (!ffa_priv_data) {
+		ffa_err("can not allocate the driver main data structure");
+		return -ENOMEM;
+	}
+
+	ffa_priv_data->dev = dev;
+
+	return 0;
+}
+
+/**
+ * ffa_probe - The driver probe function
+ * @dev:	the arm_ffa device
+ *
+ * Probing is done at boot time and triggered by the uclass device discovery.
+ * At probe level the following actions are done:
+ *	- setting the conduit
+ *	- querying the FF-A framework version
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in the resident private data structure.
+ *
+ * The probe will fail if either FF-A framework is not detected or the
+ * FF-A requests are not behaving correctly. This ensures that the
+ * driver is not installed and its operations are not exported to the clients.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = ffa_alloc_prvdata(dev);
+	if (ret != 0)
+		return ret;
+
+	ffa_set_bus_ops();
+
+	ret = ffa_set_smc_conduit();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_version();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_endpoint_id();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_cache_partitions_info();
+	if (ret != 0) {
+		ffa_free_rxtx_buffers();
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_remove - The driver remove function
+ * @dev:	the arm_ffa device
+ * When the device is about to be removed ,  unmap the RX/TX buffers and free the memory
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_remove(struct udevice *dev)
+{
+	ffa_info("removing the device");
+
+	ffa_unmap_rxtx_buffers();
+
+	if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
+		ffa_free_rxtx_buffers();
+
+	return 0;
+}
+
+/**
+ * ffa_unbind - The driver unbind function
+ * @dev:	the arm_ffa device
+ * After the device is removed and memory freed the device is unbound
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_unbind(struct udevice *dev)
+{
+	ffa_info("unbinding the device , private data already released");
+
+	ffa_priv_data = NULL;
+
+	return 0;
+}
+
+/**
+ * ffa_bus_ops_get - bus driver operations getter
+ *
+ * Return:
+ * This function returns a pointer to the driver operations structure
+ */
+const struct ffa_bus_ops *ffa_bus_ops_get(void)
+{
+	return &ffa_priv_data->ffa_ops;
+}
+
+/**
+ * ffa_bus_prvdata_get - bus driver private data getter
+ *
+ * Return:
+ * This function returns a pointer to the main private data structure
+ */
+struct ffa_prvdata **ffa_bus_prvdata_get(void)
+{
+	return &ffa_priv_data;
+}
+
+/**
+ * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
+ *
+ * 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 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.
+ * All FF-A clients should use the arm_ffa device to use the FF-A transport.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_bus_discover(void)
+{
+	int ret = 0;
+
+	if (!ffa_priv_data)
+		ret = ffa_device_get();
+
+	return ret;
+}
+
+/**
+ * Declaring the arm_ffa driver under UCLASS_FFA
+ */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.probe		= ffa_probe,
+	.remove		= ffa_remove,
+	.unbind		= ffa_unbind,
+};
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..b0c8a18926
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * Macros for displaying logs
+ */
+
+#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
+#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct  __packed ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct __packed ffa_send_direct_data {
+	unsigned long data0; /* w3/x3 */
+	unsigned long data1; /* w4/x4 */
+	unsigned long data2; /* w5/x5 */
+	unsigned long data3; /* w6/x6 */
+	unsigned long data4; /* w7/x7 */
+};
+
+/**
+ * struct ffa_bus_ops - The driver operations structure
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(const char *uuid_str,
+				  u32 *parts_size, struct ffa_partition_info *buffer);
+	int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg, bool is_smc64);
+	int (*rxtx_unmap)(void);
+};
+
+/**
+ * The device driver and the Uclass driver public functions
+ */
+
+/**
+ * ffa_bus_ops_get - driver operations getter
+ */
+const struct ffa_bus_ops *ffa_bus_ops_get(void);
+
+/**
+ * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
+ */
+int ffa_bus_discover(void);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 4b2c323452..fb59d4f356 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,9 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -55,6 +58,7 @@ enum uclass_id {
 	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v7 04/10] arm_ffa: efi: unmap RX/TX buffers
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
                                                         ` (2 preceding siblings ...)
  2022-11-07 19:20                                       ` [PATCH v7 03/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
@ 2022-11-07 19:20                                       ` Abdellatif El Khlifi
  2022-11-07 19:20                                       ` [PATCH v7 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                         ` (7 subsequent siblings)
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-07 19:20 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

unmap RX/TX buffers at ExitBootServices()

Unmapping the RX/TX buffers created by u-boot is needed before EFI
runtime.

At EFI runtime the linux kernel takes care of allocating its own RX/TX
buffers and registering them with the secure world.

Secure world should be using the RX/TX buffers created by the kernel.
So, RX/TX buffers created by u-boot must be unmapped.

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>

---

Changelog:
===============

v7: replace debug() by log_err()

lib/efi_loader/efi_boottime.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index a56021559b..b0b61bc812 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -3,6 +3,9 @@
  * EFI application boot time services
  *
  * Copyright (c) 2016 Alexander Graf
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -23,6 +26,10 @@
 #include <asm/setjmp.h>
 #include <linux/libfdt_env.h>
 
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+#include <arm_ffa.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Task priority level */
@@ -2178,6 +2185,12 @@ 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)
+		/* unmap FF-A RX/TX buffers */
+		if (ffa_bus_ops_get()->rxtx_unmap())
+			log_err("Can't unmap FF-A RX/TX buffers\n");
+#endif
+
 	/* Patch out unsupported runtime function */
 	efi_runtime_detach();
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v7 05/10] arm_ffa: introduce armffa command
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
                                                         ` (3 preceding siblings ...)
  2022-11-07 19:20                                       ` [PATCH v7 04/10] arm_ffa: efi: unmap RX/TX buffers Abdellatif El Khlifi
@ 2022-11-07 19:20                                       ` Abdellatif El Khlifi
  2022-11-07 19:20                                       ` [PATCH v7 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
                                                         ` (6 subsequent siblings)
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-07 19:20 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

Provide armffa command showcasing the use of the FF-A driver

The armffa command allows to query secure partitions data from
the secure world and exchanging messages with the partitions
using 64-bit FF-A 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>

---

Changelog:
===============

v7:

* adapt do_ffa_dev_list() following the recent update on
  uclass_first_device/uclass_next_device functions (they return void now)
* set armffa command to use 64-bit direct messaging

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

MAINTAINERS                      |   1 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   2 +
 cmd/armffa.c                     | 239 +++++++++++++++++++++++++++++++
 drivers/firmware/arm-ffa/Kconfig |   1 +
 5 files changed, 253 insertions(+)
 create mode 100644 cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 450b5725ce..e86ba068ad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,6 +266,7 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+F:	cmd/armffa.c
 F:	doc/arch/arm64.ffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 3f6bc70d43..16505361d5 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -918,6 +918,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the Arm FF-A driver
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index ca9ed1054d..adb4728b65 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,8 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
 obj-$(CONFIG_CMD_AES) += aes.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..964a5e1b34
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <arm_ffa.h>
+#include <asm/io.h>
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+
+/**
+ * do_ffa_get_singular_partition_info - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver partition_info_get operation
+ * to retrieve the data.
+ * The input UUID string is expected to be in big endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_get_singular_partition_info(struct cmd_tbl *cmdtp, int flag, int argc,
+					      char *const argv[])
+{
+	u32 count = 0, size = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	/* Mode 1: getting the number of secure partitions */
+	ret = ffa_bus_ops_get()->partition_info_get(argv[0], &count, NULL);
+	if (ret != 0) {
+		ffa_err("Failure in querying partitions count (error code: %d)", ret);
+		return ret;
+	}
+
+	if (!count) {
+		ffa_info("No secure partition found");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with ffa_partition_info structs
+	 */
+
+	ffa_info("Pre-allocating %d partition(s) info structures", count);
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	size = count * sizeof(struct ffa_partition_info);
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+
+	ret = ffa_bus_ops_get()->partition_info_get(argv[0], &size, parts_info);
+	if (ret != 0) {
+		ffa_err("Failure in querying partition(s) info (error code: %d)", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * SPs found , show the partition information
+	 */
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		ffa_info("Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x",
+			 parts_info[info_idx].id,
+			 parts_info[info_idx].exec_ctxt,
+			 parts_info[info_idx].properties);
+	}
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * do_ffa_msg_send_direct_req - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function sends data to the secure partition which the ID is provided
+ * as an argument. The function uses the arm_ffa driver sync_send_receive operation
+ * to send data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int  do_ffa_msg_send_direct_req(struct cmd_tbl *cmdtp, int flag, int argc,
+				char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	errno = 0;
+	part_id = strtoul(argv[0], NULL, 16);
+
+	if (errno) {
+		ffa_err("Invalid partition ID");
+		return -EINVAL;
+	}
+
+	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg, 1);
+	if (ret == 0) {
+		u8 cnt;
+
+		ffa_info("SP response:\n[LSB]");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			ffa_info("0x%llx", ((u64 *)&msg)[cnt]);
+	} else {
+		ffa_err("Sending direct request error (%d)", ret);
+	}
+
+	return ret;
+}
+
+/**
+ *do_ffa_dev_list - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the devices belonging to the UCLASS_FFA
+ * class. Currently, one device is expected to show up: the arm_ffa device
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_dev_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev = NULL;
+	int i;
+
+	ffa_info("arm_ffa uclass entries:");
+
+	for (i = 0, uclass_first_device(UCLASS_FFA, &dev);
+	     dev;
+	     uclass_next_device(&dev), i++) {
+		ffa_info("entry %d - instance %08x, ops %08x, plat %08x",
+			 i,
+			 (u32)map_to_sysmem(dev),
+			 (u32)map_to_sysmem(dev->driver->ops),
+			 (u32)map_to_sysmem(dev_get_plat(dev)));
+	}
+
+	return 0;
+}
+
+static struct cmd_tbl armffa_commands[] = {
+	U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_get_singular_partition_info, "", ""),
+	U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_msg_send_direct_req, "", ""),
+	U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_dev_list, "", ""),
+};
+
+/**
+ * do_armffa - the armffa command main function
+ * @cmdtp:	Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function identifies which armffa subcommand to run.
+ * Then, it makes sure the arm_ffa device is probed and
+ * ready for use.
+ * Then, it runs the subcommand.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct cmd_tbl *armffa_cmd;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
+
+	argc -= 2;
+	argv += 2;
+
+	if (!armffa_cmd || argc > armffa_cmd->maxargs)
+		return CMD_RET_USAGE;
+
+	ret = ffa_bus_discover();
+	if (ret != 0)
+		return cmd_process_error(cmdtp, ret);
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
+
+	return cmd_process_error(armffa_cmd, ret);
+}
+
+U_BOOT_CMD(armffa, 4, 1, do_armffa,
+	   "Arm FF-A operations test command",
+	   "getpart <partition UUID>\n"
+	   "	 - lists the partition(s) info\n"
+	   "ping <partition ID>\n"
+	   "	 - sends a data pattern to the specified partition\n"
+	   "devlist\n"
+	   "	 - displays the arm_ffa device info\n");
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index e4914b9bc7..be4df89d23 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -4,6 +4,7 @@ config ARM_FFA_TRANSPORT
 	bool "Enable Arm Firmware Framework for Armv8-A driver"
 	depends on DM && ARM64
 	select ARM_SMCCC
+	select CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v7 06/10] arm_ffa: introduce the FF-A Sandbox driver
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
                                                         ` (4 preceding siblings ...)
  2022-11-07 19:20                                       ` [PATCH v7 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2022-11-07 19:20                                       ` Abdellatif El Khlifi
  2022-11-07 19:20                                       ` [PATCH v7 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                         ` (5 subsequent siblings)
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-07 19:20 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

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>

---

Changelog:
===============

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               |  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 +-
 13 files changed, 939 insertions(+), 14 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 e86ba068ad..1d745b175d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -270,6 +270,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 af2ce34174..01f3b6456f 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -256,3 +256,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 f12d0a4f51..f7e8d73f75 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -334,3 +334,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 ed66f70f61..9a3d362dfc 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 ad7430ada9..a16536c2be 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 b955e5187b..4e1535abac 100644
--- a/drivers/firmware/arm-ffa/core.c
+++ b/drivers/firmware/arm-ffa/core.c
@@ -1069,6 +1069,7 @@ static int ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data
 	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
@@ -1082,6 +1083,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
@@ -1095,7 +1097,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");
@@ -1272,15 +1279,16 @@ 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 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:
@@ -1291,9 +1299,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..8e8549441d
--- /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 b0c8a18926..f51e826d47 100644
--- a/include/arm_ffa.h
+++ b/include/arm_ffa.h
@@ -86,7 +86,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(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 b0b61bc812..8f18d16173 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())
 			log_err("Can't unmap FF-A RX/TX buffers\n");
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v7 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
                                                         ` (5 preceding siblings ...)
  2022-11-07 19:20                                       ` [PATCH v7 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
@ 2022-11-07 19:20                                       ` Abdellatif El Khlifi
  2022-11-07 19:20                                       ` [PATCH v7 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                         ` (4 subsequent siblings)
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-07 19:20 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

Add functional test cases for the FF-A core driver

These tests rely on the FF-A Sandbox driver which helps in
 inspecting the FF-A core driver.

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>

---

Changelog:
===============

v7: set the tests to use 64-bit direct messaging

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

v1: introduce sandbox tests

MAINTAINERS      |   1 +
 test/dm/Makefile |   2 +
 test/dm/ffa.c    | 394 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 397 insertions(+)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 1d745b175d..d87f1865b5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -271,6 +271,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/sandbox_arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/test/dm/Makefile b/test/dm/Makefile
index cc3cc454f7..9691821f81 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# (C) Copyright 2022 ARM Limited
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -83,6 +84,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_SANDBOX_FFA) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..14b19cf71e
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <dm.h>
+#include <dm/test.h>
+#include "../../drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h"
+#include <sandbox_arm_ffa.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Macros */
+
+#define LOG_MSG_SZ (100)
+#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
+
+/* Functional tests for the UCLASS_FFA */
+
+static int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
+{
+	char cmd[LOG_CMD_SZ] = {0};
+
+	console_record_reset();
+
+	snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
+	run_command(cmd, 0);
+
+	ut_assert_console_end();
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_fwk_version(struct ffa_prvdata *prvdata, struct sandbox_ffa_prvdata *sdx_prvdata,
+			     struct unit_test_state *uts)
+{
+	if (prvdata->fwk_version != sdx_prvdata->fwk_version) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: framework version: core = 0x%x , sandbox  = 0x%x", __func__,
+			 prvdata->fwk_version,
+			sdx_prvdata->fwk_version);
+
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_endpoint_id(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (prvdata->id) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: endpoint id: core = 0x%x", __func__, prvdata->id);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_core_dev(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->dev) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: core device NULL", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_sandbox_dev(struct sandbox_ffa_prvdata *sdx_prvdata, struct unit_test_state *uts)
+{
+	if (!sdx_prvdata->dev) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: sandbox device NULL", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_rxtxbuf(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->pair.rxbuf && prvdata->pair.txbuf) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = 0x%llx txbuf = 0x%llx", __func__,
+			 prvdata->pair.rxbuf,
+			 prvdata->pair.txbuf);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_features(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	if (prvdata->pair.rxtx_min_pages != RXTX_4K &&
+	    prvdata->pair.rxtx_min_pages != RXTX_16K &&
+	    prvdata->pair.rxtx_min_pages != RXTX_64K) {
+		snprintf(msg,
+			 LOG_MSG_SZ,
+			 "[%s]: Error: FFA_RXTX_MAP features = 0x%lx",
+			 __func__,
+			 prvdata->pair.rxtx_min_pages);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+	{
+		if (rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	case FFA_RXTX_UNMAP:
+	{
+		if (!rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	default:
+		return CMD_RET_FAILURE;
+	}
+
+	snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__,
+		 (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP"));
+	dm_test_ffa_log(uts, msg);
+
+	return CMD_RET_FAILURE;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	if (rxbuf_owned) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg = {0};
+	u8 cnt;
+
+	ut_assertok(ffa_bus_ops_get()->sync_send_receive(part_id, &msg, 1));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_assertok(((u64 *)&msg)[cnt] != 0xffffffffffffffff);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct sandbox_ffa_prvdata *sdx_prvdata,
+				     struct unit_test_state *uts)
+{
+	u32 count = 0, size = 0;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx, exp_info_idx;
+	int ret;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &count, NULL);
+	/* make sure partitions are detected */
+	ut_assertok(ret != 0);
+	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	ut_assertok(!parts_info);
+
+	size = count * sizeof(struct ffa_partition_info);
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &size, parts_info);
+	if (ret != 0) {
+		free(parts_info);
+		ut_assertok(ret != 0);
+	}
+
+	/*
+	 * SPs found , verify the partitions information
+	 */
+
+	ret = CMD_RET_FAILURE;
+
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		for (exp_info_idx = 0;
+		     exp_info_idx < sdx_prvdata->partitions.count;
+		     exp_info_idx++) {
+			if (parts_info[info_idx].id ==
+			   sdx_prvdata->partitions.descs[exp_info_idx].info.id) {
+				ret = memcmp(&parts_info[info_idx],
+					     &sdx_prvdata->partitions.descs[exp_info_idx]
+					     .info,
+					     sizeof(struct ffa_partition_info));
+				if (ret)
+					free(parts_info);
+				ut_assertok(ret != 0);
+				/* send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
+			}
+			ret = CMD_RET_SUCCESS;
+		}
+	}
+
+	free(parts_info);
+
+	/* Verify  expected partitions found in the emulated secure world*/
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+	struct ffa_sandbox_data func_data = {0};
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	int ret;
+
+	/*  test probing FF-A devices */
+	ut_assertok(ffa_bus_discover());
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+
+	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
+
+	/* make sure private data pointers are retrieved */
+	ut_assertok(prvdata == 0);
+	ut_assertok(sdx_prvdata == 0);
+
+	/* make sure dev devices created */
+	ut_assertok(check_core_dev(prvdata, uts));
+	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
+
+	/* test FFA_VERSION */
+	ut_assertok(check_fwk_version(prvdata, sdx_prvdata, uts));
+
+	/* test FFA_ID_GET */
+	ut_assertok(check_endpoint_id(prvdata, uts));
+
+	/* test FFA_FEATURES */
+	ut_assertok(check_features(prvdata, uts));
+
+	/*  test core RX/TX buffers */
+	ut_assertok(check_rxtxbuf(prvdata, uts));
+
+	/* test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_MAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc1_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc2_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* test FFA_RXTX_UNMAP */
+	ut_assertok(ffa_bus_ops_get()->rxtx_unmap());
+
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_UNMAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+	struct ffa_sandbox_data func_data = {0};
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	u32 count = 0;
+	u16 part_id = 0;
+
+	/*  test probing FF-A devices */
+	ut_assertok(ffa_bus_discover());
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+
+	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
+
+	/* make sure private data pointers are retrieved */
+	ut_assertok(prvdata == 0);
+	ut_assertok(sdx_prvdata == 0);
+
+	/* make sure dev devices created */
+	ut_assertok(check_core_dev(prvdata, uts));
+	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
+
+	/* query partitions count using  invalid arguments  */
+	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, NULL, NULL);
+	ut_assertok(ret != -EINVAL);
+
+	/* query partitions count using an invalid UUID  string */
+	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid_str, &count, NULL);
+	ut_assertok(ret != -EINVAL);
+
+	/* query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, &count, NULL);
+	ut_assertok(count != 0);
+
+	/* query partitions count using a valid UUID  */
+	count = 0;
+	ret = ffa_bus_ops_get()->partition_info_get(valid_svc_uuid, &count, NULL);
+	/* make sure partitions are detected */
+	ut_assertok(ret != 0);
+	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
+
+	/* send data to an invalid partition */
+	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg, 1);
+	ut_assertok(ret != -EINVAL);
+
+	/* send data to a valid partition */
+	part_id = prvdata->partitions.descs[0].info.id;
+	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg, 1);
+	ut_assertok(ret != 0);
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v7 08/10] arm_ffa: introduce armffa command Sandbox test
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
                                                         ` (6 preceding siblings ...)
  2022-11-07 19:20                                       ` [PATCH v7 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2022-11-07 19:20                                       ` Abdellatif El Khlifi
  2022-11-07 19:20                                       ` [PATCH v7 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
                                                         ` (3 subsequent siblings)
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-07 19:20 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

Add Sandbox test for the armffa command

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>

---

Changelog:
===============

v4: drop use of helper APIs

v1: introduce armffa command sandbox test

MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 40 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 43 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d87f1865b5..729e11a69f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -271,6 +271,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/sandbox_arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 6dd6e81875..4c40aefb3b 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# (C) Copyright 2022 ARM Limited
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -18,5 +19,6 @@ obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PWM) += pwm.o
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_SANDBOX_FFA) += armffa.o
 endif
 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..531f82066e
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <sandbox_arm_ffa.h>
+#include <string.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define PING_CMD_SIZE 19
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	char ping_cmd[PING_CMD_SIZE] = {0};
+
+	ut_assertok(ffa_bus_discover());
+
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	snprintf(ping_cmd, PING_CMD_SIZE, "armffa ping 0x%x", SANDBOX_SP1_ID);
+
+	/* armffa ping <ID> */
+	ut_assertok(run_command(ping_cmd, 0));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v7 09/10] arm_ffa: efi: introduce FF-A MM communication
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
                                                         ` (7 preceding siblings ...)
  2022-11-07 19:20                                       ` [PATCH v7 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2022-11-07 19:20                                       ` Abdellatif El Khlifi
  2022-11-15  9:03                                         ` Ilias Apalodimas
  2022-11-07 19:20                                       ` [PATCH v7 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
                                                         ` (2 subsequent siblings)
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-07 19:20 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong,
	Gowtham Suresh Kumar

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

MM communication protocol supports FF-A 64-bit direct messaging.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>

---

Changelog:
===============

v7:

* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make mm_sp_svc_uuid static
* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
* improve use of unmap_sysmem() in ffa_mm_communicate()

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

include/mm_communication.h        |   5 +
 lib/efi_loader/Kconfig            |  14 +-
 lib/efi_loader/efi_variable_tee.c | 269 +++++++++++++++++++++++++++++-
 3 files changed, 282 insertions(+), 6 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..d409bed777 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,8 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +15,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 41756ea539..f0d843d5ca 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -60,13 +60,23 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	depends on OPTEE && ARM_FFA_TRANSPORT
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..ec5ea4fd63 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,6 +4,8 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright (C) 2022 ARM Limited
+ *  Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -15,6 +17,36 @@
 #include <malloc.h>
 #include <mm_communication.h>
 
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+#include <arm_ffa.h>
+#include <cpu_func.h>
+#include <mapmem.h>
+
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_SIZE 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_OFFSET
+#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_OFFSET 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_ADDR 0
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+
+static const char *mm_sp_svc_uuid = MM_SP_UUID;
+
+static u16 mm_sp_id;
+
+#endif
+
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -24,6 +56,7 @@ struct mm_connection {
 	u32 session;
 };
 
+#if (IS_ENABLED(CONFIG_OPTEE))
 /**
  * get_connection() - Retrieve OP-TEE session for a specific UUID.
  *
@@ -143,13 +176,229 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 
 	return ret;
 }
+#endif
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+/**
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notifies the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret = -1;
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
+
+	ret = ffa_bus_ops_get()->sync_send_receive(mm_sp_id, &msg, 1);
+	if (ret != 0)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	if (sp_event_ret == MM_SUCCESS)
+		return 0;
+
+	/*
+	 * Failure to notify the MM SP
+	 */
+
+	return -EACCES;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0, size = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &count, NULL);
+	if (ret != 0) {
+		log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
+		return ret;
+	}
+
+	if (!count) {
+		log_info("EFI: No MM partition found\n");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -ENOMEM;
+
+	size = count * sizeof(struct ffa_partition_info);
+
+	/*
+	 * ask the driver to fill the
+	 * buffer with the SPs info
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &size, parts_info);
+	if (ret != 0) {
+		log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * MM SPs found , use the first one
+	 */
+
+	mm_sp_id = parts_info[0].id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	free(parts_info);
+
+	return 0;
+}
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	efi_status_t efi_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
+		log_err("EFI: Failure to discover MM partition ID at boot time\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+	#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+	#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+
+	switch (ffa_ret) {
+	case 0:
+	{
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		efi_ret = EFI_SUCCESS;
+		break;
+	}
+	case -EINVAL:
+		efi_ret = EFI_DEVICE_ERROR;
+		break;
+	case -EPERM:
+		efi_ret = EFI_INVALID_PARAMETER;
+		break;
+	case -EACCES:
+		efi_ret = EFI_ACCESS_DENIED;
+		break;
+	case -EBUSY:
+		efi_ret = EFI_OUT_OF_RESOURCES;
+		break;
+	default:
+		efi_ret = EFI_ACCESS_DENIED;
+	}
+
+	unmap_sysmem(virt_shared_buf);
+	return efi_ret;
+}
+#endif
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
@@ -162,7 +411,12 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+	ret = ffa_bus_discover();
+	if (ret != 0)
+		ret = optee_mm_communicate(comm_buf, dsize);
+	else
+		ret = ffa_mm_communicate(comm_buf, dsize);
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -258,6 +512,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
 		goto out;
 	}
 	*size = var_payload->size;
+
+	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
+			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
+				MM_VARIABLE_COMMUNICATE_SIZE;
+	#endif
+
 	/*
 	 * There seems to be a bug in EDK2 miscalculating the boundaries and
 	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
@@ -697,7 +958,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v7 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
                                                         ` (8 preceding siblings ...)
  2022-11-07 19:20                                       ` [PATCH v7 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2022-11-07 19:20                                       ` Abdellatif El Khlifi
  2022-11-11 14:42                                       ` [PATCH v7 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2022-11-22 13:17                                       ` [PATCH v8 " Abdellatif El Khlifi
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-07 19:20 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

turn on EFI MM communication

On corstone1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

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>

---

Changelog:
===============

v7:

* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
  FFA_SHARED_MM_BUFFER_OFFSET
* update FFA_SHARED_MM_BUFFER_ADDR value

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

configs/corstone1000_defconfig | 4 ++++
 include/configs/corstone1000.h | 9 +++++++++
 2 files changed, 13 insertions(+)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index dddfa27507..d827dd72f1 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -52,3 +52,7 @@ CONFIG_DM_SERIAL=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760=y
 CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
index 8e0230c135..0362d29ac2 100644
--- a/include/configs/corstone1000.h
+++ b/include/configs/corstone1000.h
@@ -14,6 +14,15 @@
 
 #include <linux/sizes.h>
 
+#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
+
+/*
+ * shared buffer physical address used for communication between
+ * u-boot and the MM SP
+ */
+#define FFA_SHARED_MM_BUFFER_ADDR	0x02000000UL
+#define FFA_SHARED_MM_BUFFER_OFFSET	0
+
 #define V2M_BASE		0x80000000
 
 #define CONFIG_PL011_CLOCK	50000000
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 02/10] lib: uuid: introduce be_uuid_str_to_le_bin function
  2022-10-24 12:07                                       ` Ilias Apalodimas
@ 2022-11-08 10:45                                         ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-08 10:45 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, nd

On Mon, Oct 24, 2022 at 03:07:35PM +0300, Ilias Apalodimas wrote:
> Hi Abdellatif, 
> 
> On Thu, Oct 13, 2022 at 11:38:49AM +0100, Abdellatif El Khlifi wrote:
> > convert big endian UUID string to little endian buffer
> 
> You don't really need the be_ suffix on the declaration, endianness doesn't
> apply to strings.  Can't we do something similar to uuid_str_to_bin() and
> just convert to LE?

Thanks, done in v7 [1]. Please have a look.

[1]: https://lore.kernel.org/all/20221107192055.21669-3-abdellatif.elkhlifi@arm.com/

> 
> Thanks
> /Ilias
> > 
> > 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>
> > 
> > ---
> > 
> > Changelog:
> > ===============
> > 
> > v4:
> > 
> > * rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
> >   a standalone commit (the current)
> > 
> > v3:
> > 
> > * introduce ffa_uuid_str_to_bin (provided by
> >   arm_ffa: introduce Arm FF-A low-level driver)
> > 
> > include/uuid.h |  8 +++++++
> >  lib/uuid.c     | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 72 insertions(+)
> > 
> > diff --git a/include/uuid.h b/include/uuid.h
> > index 4a4883d3b5..ad3af350f9 100644
> > --- a/include/uuid.h
> > +++ b/include/uuid.h
> > @@ -2,6 +2,8 @@
> >  /*
> >   * Copyright (C) 2014 Samsung Electronics
> >   * Przemyslaw Marczak <p.marczak@samsung.com>
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  #ifndef __UUID_H__
> >  #define __UUID_H__
> > @@ -44,4 +46,10 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
> >  const char *uuid_guid_get_str(const unsigned char *guid_bin);
> >  void gen_rand_uuid(unsigned char *uuid_bin);
> >  void gen_rand_uuid_str(char *uuid_str, int str_format);
> > +
> > +/**
> > + * be_uuid_str_to_le_bin - Converts a big endian UUID string to a little endian buffer
> > + */
> > +int be_uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
> > +
> >  #endif
> > diff --git a/lib/uuid.c b/lib/uuid.c
> > index 465e1ac38f..15a9ab49d5 100644
> > --- a/lib/uuid.c
> > +++ b/lib/uuid.c
> > @@ -1,6 +1,8 @@
> >  // SPDX-License-Identifier: GPL-2.0+
> >  /*
> >   * Copyright 2011 Calxeda, Inc.
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  
> >  #include <common.h>
> > @@ -346,6 +348,68 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
> >  	return 0;
> >  }
> >  
> > +/**
> > + * be_uuid_str_to_le_bin - Converts a big endian UUID string to a little endian buffer
> > + * @uuid_str:	UUID string in big endian format (36 bytes wide + '/0')
> > + * @uuid_bin:	preallocated 16 bytes UUID buffer in little endian format
> > + *
> > + * UUID string is 36 characters (36 bytes):
> > + *
> > + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
> > + * be		     be	     be	      be      be
> > + *
> > + * where x is a hexadecimal character. Fields are separated by '-'s.
> > + * When converting to a binary UUID, these endianness rules apply:
> > + *     be: means the field in the string is considered a big endian hex number
> > + *	   and should be converted to little endian binary format
> > + *
> > + * Return:
> > + *
> > + *    uuid_bin filled with little endian UUID data
> > + *    On success 0 is returned. Otherwise, failure code.
> > + */
> > +int be_uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
> > +{
> > +	u16 tmp16 = 0;
> > +	u32 tmp32 = 0;
> > +	u64 tmp64 = 0;
> > +
> > +	if (!uuid_str_valid(uuid_str) || !uuid_bin)
> > +		return -EINVAL;
> > +
> > +	/*
> > +	 * reverse bytes from big to little endian
> > +	 */
> > +	tmp32 = simple_strtoul(uuid_str, NULL, 16);
> > +	memcpy(uuid_bin, &tmp32, 4);
> > +
> > +	/*
> > +	 * reverse bytes from big to little endian
> > +	 */
> > +	tmp16 = simple_strtoul(uuid_str + 9, NULL, 16);
> > +	memcpy(uuid_bin + 4, &tmp16, 2);
> > +
> > +	/*
> > +	 * reverse bytes from big to little endian
> > +	 */
> > +	tmp16 = simple_strtoul(uuid_str + 14, NULL, 16);
> > +	memcpy(uuid_bin + 6, &tmp16, 2);
> > +
> > +	/*
> > +	 * reverse bytes from big to little endian
> > +	 */
> > +	tmp16 = simple_strtoul(uuid_str + 19, NULL, 16);
> > +	memcpy(uuid_bin + 8, &tmp16, 2);
> > +
> > +	/*
> > +	 * reverse bytes from big to little endian
> > +	 */
> > +	tmp64 = simple_strtoull(uuid_str + 24, NULL, 16);
> > +	memcpy(uuid_bin + 10, (char *)&tmp64, 6);
> > +
> > +	return 0;
> > +}
> > +
> >  /*
> >   * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
> >   *
> > -- 
> > 2.17.1
> > 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 04/10] arm_ffa: efi: unmap RX/TX buffers
  2022-10-24 12:08                                       ` Ilias Apalodimas
@ 2022-11-08 10:48                                         ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-08 10:48 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, nd

On Mon, Oct 24, 2022 at 03:08:53PM +0300, Ilias Apalodimas wrote:
> On Thu, Oct 13, 2022 at 11:38:51AM +0100, Abdellatif El Khlifi wrote:
> > unmap RX/TX buffers at ExitBootServices()
> > 
> > Unmapping the RX/TX buffers created by u-boot is needed before EFI
> > runtime.
> > 
> > At EFI runtime the linux kernel takes care of allocating its own RX/TX
> > buffers and registering them with the secure world.
> > 
> > Secure world should be using the RX/TX buffers created by the kernel.
> > So, RX/TX buffers created by u-boot must be unmapped.
> > 
> > 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>
> > ---
> >  lib/efi_loader/efi_boottime.c | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> > 
> > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> > index a56021559b..2054b33568 100644
> > --- a/lib/efi_loader/efi_boottime.c
> > +++ b/lib/efi_loader/efi_boottime.c
> > @@ -3,6 +3,9 @@
> >   * EFI application boot time services
> >   *
> >   * Copyright (c) 2016 Alexander Graf
> > + *
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  
> >  #include <common.h>
> > @@ -23,6 +26,10 @@
> >  #include <asm/setjmp.h>
> >  #include <linux/libfdt_env.h>
> >  
> > +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
> > +#include <arm_ffa.h>
> > +#endif
> > +
> >  DECLARE_GLOBAL_DATA_PTR;
> >  
> >  /* Task priority level */
> > @@ -2178,6 +2185,14 @@ 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)
> > +		/* 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");
> 
> Just do log_err() here and get rid of the else

Thanks. Done in v7.

> 
> > +		else
> > +			debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
> > +#endif
> > +
> >  	/* Patch out unsupported runtime function */
> >  	efi_runtime_detach();
> >  
> > -- 
> > 2.17.1
> > 
> 
> Thanks
> /Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  2022-10-24 12:10                                       ` Ilias Apalodimas
@ 2022-11-08 10:53                                         ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-08 10:53 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: sjg, u-boot, nd

On Mon, Oct 24, 2022 at 03:10:09PM +0300, Ilias Apalodimas wrote:
> Hi Abdellatif
> On Thu, Oct 13, 2022 at 11:38:54AM +0100, Abdellatif El Khlifi wrote:
> > Add functional test cases for the FF-A core driver
> > 
> > These tests rely on the FF-A Sandbox driver which helps in
> >  inspecting the FF-A core driver.
> 
> This looks ok from me, but I'd prefer Simon having a quick look, since I am
> not an expert when it comes to sandbox and testing 

Thanks for the feedback Ilias.

Simon, could you please provide a feedback about the Sandbox part ?
> 
> Thanks
> /Ilias
> > 
> > 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>
> > 
> > ---
> > 
> > Changelog:
> > ===============
> > 
> > v4: align sandbox tests with the new FF-A driver interfaces
> >  and new way of error handling
> > 
> > v1: introduce sandbox tests
> > 
> >  MAINTAINERS      |   1 +
> >  test/dm/Makefile |   2 +
> >  test/dm/ffa.c    | 394 +++++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 397 insertions(+)
> >  create mode 100644 test/dm/ffa.c
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 598ae76e16..bf198f4ce1 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -256,6 +256,7 @@ F:	doc/arch/arm64.ffa.rst
> >  F:	drivers/firmware/arm-ffa/
> >  F:	include/arm_ffa.h
> >  F:	include/sandbox_arm_ffa.h
> > +F:	test/dm/ffa.c
> >  
> >  ARM FREESCALE IMX
> >  M:	Stefano Babic <sbabic@denx.de>
> > diff --git a/test/dm/Makefile b/test/dm/Makefile
> > index 5178daa7cf..e5bc4b4bd6 100644
> > --- a/test/dm/Makefile
> > +++ b/test/dm/Makefile
> > @@ -1,6 +1,7 @@
> >  # SPDX-License-Identifier: GPL-2.0+
> >  #
> >  # Copyright (c) 2013 Google, Inc
> > +# (C) Copyright 2022 ARM Limited
> >  
> >  obj-$(CONFIG_UT_DM) += test-dm.o
> >  
> > @@ -81,6 +82,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
> >  obj-$(CONFIG_ACPI_PMC) += pmc.o
> >  obj-$(CONFIG_DM_PMIC) += pmic.o
> >  obj-$(CONFIG_DM_PWM) += pwm.o
> > +obj-$(CONFIG_SANDBOX_FFA) += ffa.o
> >  obj-$(CONFIG_QFW) += qfw.o
> >  obj-$(CONFIG_RAM) += ram.o
> >  obj-y += regmap.o
> > diff --git a/test/dm/ffa.c b/test/dm/ffa.c
> > new file mode 100644
> > index 0000000000..052d5fc3f4
> > --- /dev/null
> > +++ b/test/dm/ffa.c
> > @@ -0,0 +1,394 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Functional tests for UCLASS_FFA  class
> > + *
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include <common.h>
> > +#include <console.h>
> > +#include <dm.h>
> > +#include <dm/test.h>
> > +#include "../../drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h"
> > +#include <sandbox_arm_ffa.h>
> > +#include <test/test.h>
> > +#include <test/ut.h>
> > +
> > +/* Macros */
> > +
> > +#define LOG_MSG_SZ (100)
> > +#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
> > +
> > +/* Functional tests for the UCLASS_FFA */
> > +
> > +static int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
> > +{
> > +	char cmd[LOG_CMD_SZ] = {0};
> > +
> > +	console_record_reset();
> > +
> > +	snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
> > +	run_command(cmd, 0);
> > +
> > +	ut_assert_console_end();
> > +
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +static int check_fwk_version(struct ffa_prvdata *prvdata, struct sandbox_ffa_prvdata *sdx_prvdata,
> > +			     struct unit_test_state *uts)
> > +{
> > +	if (prvdata->fwk_version != sdx_prvdata->fwk_version) {
> > +		char msg[LOG_MSG_SZ] = {0};
> > +
> > +		snprintf(msg, LOG_MSG_SZ,
> > +			 "[%s]: Error: framework version: core = 0x%x , sandbox  = 0x%x", __func__,
> > +			 prvdata->fwk_version,
> > +			sdx_prvdata->fwk_version);
> > +
> > +		dm_test_ffa_log(uts, msg);
> > +		return CMD_RET_FAILURE;
> > +	}
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +static int check_endpoint_id(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
> > +{
> > +	if (prvdata->id) {
> > +		char msg[LOG_MSG_SZ] = {0};
> > +
> > +		snprintf(msg, LOG_MSG_SZ,
> > +			 "[%s]: Error: endpoint id: core = 0x%x", __func__, prvdata->id);
> > +		dm_test_ffa_log(uts, msg);
> > +		return CMD_RET_FAILURE;
> > +	}
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +static int check_core_dev(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
> > +{
> > +	if (!prvdata->dev) {
> > +		char msg[LOG_MSG_SZ] = {0};
> > +
> > +		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: core device NULL", __func__);
> > +		dm_test_ffa_log(uts, msg);
> > +		return CMD_RET_FAILURE;
> > +	}
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +static int check_sandbox_dev(struct sandbox_ffa_prvdata *sdx_prvdata, struct unit_test_state *uts)
> > +{
> > +	if (!sdx_prvdata->dev) {
> > +		char msg[LOG_MSG_SZ] = {0};
> > +
> > +		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: sandbox device NULL", __func__);
> > +		dm_test_ffa_log(uts, msg);
> > +		return CMD_RET_FAILURE;
> > +	}
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +static int check_rxtxbuf(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
> > +{
> > +	if (!prvdata->pair.rxbuf && prvdata->pair.txbuf) {
> > +		char msg[LOG_MSG_SZ] = {0};
> > +
> > +		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = 0x%llx txbuf = 0x%llx", __func__,
> > +			 prvdata->pair.rxbuf,
> > +			 prvdata->pair.txbuf);
> > +		dm_test_ffa_log(uts, msg);
> > +		return CMD_RET_FAILURE;
> > +	}
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +static int check_features(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
> > +{
> > +	char msg[LOG_MSG_SZ] = {0};
> > +
> > +	if (prvdata->pair.rxtx_min_pages != RXTX_4K &&
> > +	    prvdata->pair.rxtx_min_pages != RXTX_16K &&
> > +	    prvdata->pair.rxtx_min_pages != RXTX_64K) {
> > +		snprintf(msg,
> > +			 LOG_MSG_SZ,
> > +			 "[%s]: Error: FFA_RXTX_MAP features = 0x%lx",
> > +			 __func__,
> > +			 prvdata->pair.rxtx_min_pages);
> > +		dm_test_ffa_log(uts, msg);
> > +		return CMD_RET_FAILURE;
> > +	}
> > +
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +static int check_rxbuf_mapped_flag(u32 queried_func_id,
> > +				   u8 rxbuf_mapped,
> > +				   struct unit_test_state *uts)
> > +{
> > +	char msg[LOG_MSG_SZ] = {0};
> > +
> > +	switch (queried_func_id) {
> > +	case FFA_RXTX_MAP:
> > +	{
> > +		if (rxbuf_mapped)
> > +			return CMD_RET_SUCCESS;
> > +		break;
> > +	}
> > +	case FFA_RXTX_UNMAP:
> > +	{
> > +		if (!rxbuf_mapped)
> > +			return CMD_RET_SUCCESS;
> > +		break;
> > +	}
> > +	default:
> > +		return CMD_RET_FAILURE;
> > +	}
> > +
> > +	snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__,
> > +		 (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP"));
> > +	dm_test_ffa_log(uts, msg);
> > +
> > +	return CMD_RET_FAILURE;
> > +}
> > +
> > +static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
> > +{
> > +	if (rxbuf_owned) {
> > +		char msg[LOG_MSG_SZ] = {0};
> > +
> > +		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__);
> > +		dm_test_ffa_log(uts, msg);
> > +		return CMD_RET_FAILURE;
> > +	}
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
> > +{
> > +	struct ffa_send_direct_data msg = {0};
> > +	u8 cnt;
> > +
> > +	ut_assertok(ffa_bus_ops_get()->sync_send_receive(part_id, &msg));
> > +
> > +	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
> > +		ut_assertok(((u64 *)&msg)[cnt] != 0xffffffffffffffff);
> > +
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +static int test_partitions_and_comms(const char *service_uuid,
> > +				     struct sandbox_ffa_prvdata *sdx_prvdata,
> > +				     struct unit_test_state *uts)
> > +{
> > +	u32 count = 0, size = 0;
> > +	struct ffa_partition_info *parts_info;
> > +	u32 info_idx, exp_info_idx;
> > +	int ret;
> > +
> > +	/*
> > +	 * get from the driver the count of the SPs matching the UUID
> > +	 */
> > +	ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &count, NULL);
> > +	/* make sure partitions are detected */
> > +	ut_assertok(ret != 0);
> > +	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
> > +
> > +	/*
> > +	 * pre-allocate a buffer to be filled by the driver
> > +	 * with	 ffa_partition_info structs
> > +	 */
> > +
> > +	parts_info = calloc(count, sizeof(struct ffa_partition_info));
> > +	ut_assertok(!parts_info);
> > +
> > +	size = count * sizeof(struct ffa_partition_info);
> > +
> > +	/*
> > +	 * ask the driver to fill the buffer with the SPs info
> > +	 */
> > +	ret = ffa_bus_ops_get()->partition_info_get(service_uuid, &size, parts_info);
> > +	if (ret != 0) {
> > +		free(parts_info);
> > +		ut_assertok(ret != 0);
> > +	}
> > +
> > +	/*
> > +	 * SPs found , verify the partitions information
> > +	 */
> > +
> > +	ret = CMD_RET_FAILURE;
> > +
> > +	for (info_idx = 0; info_idx < count ; info_idx++) {
> > +		for (exp_info_idx = 0;
> > +		     exp_info_idx < sdx_prvdata->partitions.count;
> > +		     exp_info_idx++) {
> > +			if (parts_info[info_idx].id ==
> > +			   sdx_prvdata->partitions.descs[exp_info_idx].info.id) {
> > +				ret = memcmp(&parts_info[info_idx],
> > +					     &sdx_prvdata->partitions.descs[exp_info_idx]
> > +					     .info,
> > +					     sizeof(struct ffa_partition_info));
> > +				if (ret)
> > +					free(parts_info);
> > +				ut_assertok(ret != 0);
> > +				/* send and receive data from the current partition */
> > +				test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
> > +			}
> > +			ret = CMD_RET_SUCCESS;
> > +		}
> > +	}
> > +
> > +	free(parts_info);
> > +
> > +	/* Verify  expected partitions found in the emulated secure world*/
> > +	ut_assertok(ret != CMD_RET_SUCCESS);
> > +
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +static int dm_test_ffa_ack(struct unit_test_state *uts)
> > +{
> > +	struct ffa_prvdata *prvdata = NULL;
> > +	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
> > +	struct ffa_sandbox_data func_data = {0};
> > +	u8 rxbuf_flag = 0;
> > +	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
> > +	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
> > +	int ret;
> > +
> > +	/*  test probing FF-A devices */
> > +	ut_assertok(ffa_bus_discover());
> > +
> > +	/* get a pointer to the FF-A core and sandbox drivers private data */
> > +	func_data.data0 = &prvdata;
> > +	func_data.data0_size = sizeof(prvdata);
> > +	func_data.data1 = &sdx_prvdata;
> > +	func_data.data1_size = sizeof(sdx_prvdata);
> > +
> > +	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
> > +
> > +	/* make sure private data pointers are retrieved */
> > +	ut_assertok(prvdata == 0);
> > +	ut_assertok(sdx_prvdata == 0);
> > +
> > +	/* make sure dev devices created */
> > +	ut_assertok(check_core_dev(prvdata, uts));
> > +	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
> > +
> > +	/* test FFA_VERSION */
> > +	ut_assertok(check_fwk_version(prvdata, sdx_prvdata, uts));
> > +
> > +	/* test FFA_ID_GET */
> > +	ut_assertok(check_endpoint_id(prvdata, uts));
> > +
> > +	/* test FFA_FEATURES */
> > +	ut_assertok(check_features(prvdata, uts));
> > +
> > +	/*  test core RX/TX buffers */
> > +	ut_assertok(check_rxtxbuf(prvdata, uts));
> > +
> > +	/* test FFA_RXTX_MAP */
> > +	func_data.data0 = &rxbuf_flag;
> > +	func_data.data0_size = sizeof(rxbuf_flag);
> > +
> > +	rxbuf_flag = 0;
> > +	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_MAP, &func_data));
> > +	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts));
> > +
> > +	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
> > +	ret = test_partitions_and_comms(svc1_uuid, sdx_prvdata, uts);
> > +	ut_assertok(ret != CMD_RET_SUCCESS);
> > +
> > +	/* test FFA_RX_RELEASE */
> > +	rxbuf_flag = 1;
> > +	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
> > +	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
> > +
> > +	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
> > +	ret = test_partitions_and_comms(svc2_uuid, sdx_prvdata, uts);
> > +	ut_assertok(ret != CMD_RET_SUCCESS);
> > +
> > +	/* test FFA_RX_RELEASE */
> > +	rxbuf_flag = 1;
> > +	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
> > +	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
> > +
> > +	/* test FFA_RXTX_UNMAP */
> > +	ut_assertok(ffa_bus_ops_get()->rxtx_unmap());
> > +
> > +	rxbuf_flag = 1;
> > +	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_UNMAP, &func_data));
> > +	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts));
> > +
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
> > +
> > +static int dm_test_ffa_nack(struct unit_test_state *uts)
> > +{
> > +	struct ffa_prvdata *prvdata = NULL;
> > +	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
> > +	struct ffa_sandbox_data func_data = {0};
> > +	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
> > +	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
> > +	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
> > +	struct ffa_send_direct_data msg = {0};
> > +	int ret;
> > +	u32 count = 0;
> > +	u16 part_id = 0;
> > +
> > +	/*  test probing FF-A devices */
> > +	ut_assertok(ffa_bus_discover());
> > +
> > +	/* get a pointer to the FF-A core and sandbox drivers private data */
> > +	func_data.data0 = &prvdata;
> > +	func_data.data0_size = sizeof(prvdata);
> > +	func_data.data1 = &sdx_prvdata;
> > +	func_data.data1_size = sizeof(sdx_prvdata);
> > +
> > +	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
> > +
> > +	/* make sure private data pointers are retrieved */
> > +	ut_assertok(prvdata == 0);
> > +	ut_assertok(sdx_prvdata == 0);
> > +
> > +	/* make sure dev devices created */
> > +	ut_assertok(check_core_dev(prvdata, uts));
> > +	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
> > +
> > +	/* query partitions count using  invalid arguments  */
> > +	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, NULL, NULL);
> > +	ut_assertok(ret != -EINVAL);
> > +
> > +	/* query partitions count using an invalid UUID  string */
> > +	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid_str, &count, NULL);
> > +	ut_assertok(ret != -EINVAL);
> > +
> > +	/* query partitions count using an invalid UUID (no matching SP) */
> > +	count = 0;
> > +	ret = ffa_bus_ops_get()->partition_info_get(unvalid_svc_uuid, &count, NULL);
> > +	ut_assertok(count != 0);
> > +
> > +	/* query partitions count using a valid UUID  */
> > +	count = 0;
> > +	ret = ffa_bus_ops_get()->partition_info_get(valid_svc_uuid, &count, NULL);
> > +	/* make sure partitions are detected */
> > +	ut_assertok(ret != 0);
> > +	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
> > +
> > +	/* send data to an invalid partition */
> > +	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
> > +	ut_assertok(ret != -EINVAL);
> > +
> > +	/* send data to a valid partition */
> > +	part_id = prvdata->partitions.descs[0].info.id;
> > +	ret = ffa_bus_ops_get()->sync_send_receive(part_id, &msg);
> > +	ut_assertok(ret != 0);
> > +
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
> > -- 
> > 2.17.1
> > 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 09/10] arm_ffa: efi: introduce FF-A MM communication
  2022-10-24 12:30                                       ` Ilias Apalodimas
@ 2022-11-08 10:58                                         ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-08 10:58 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, nd

On Mon, Oct 24, 2022 at 03:30:11PM +0300, Ilias Apalodimas wrote:
> Hi Abdellatif,
> 
> [...]
> 
> >  
> >  #include <common.h>
> > @@ -15,6 +17,36 @@
> >  #include <malloc.h>
> >  #include <mm_communication.h>
> >  
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +
> > +#include <arm_ffa.h>
> > +#include <cpu_func.h>
> > +#include <mapmem.h>
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> > +#warning "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_SIZE 0
> > +#endif
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_OFFSET
> > +#warning "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_OFFSET 0
> > +#endif
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> > +#warning "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_ADDR 0
> > +#endif
> 
> Is the device going to work with these defaults? I am assuming not, so
> isn't better to treat this as compile time errors?

Thanks. Done in v7.

> 
> > +
> > +/* MM return codes */
> > +#define MM_SUCCESS (0)
> > +
> > +const char *mm_sp_svc_uuid = MM_SP_UUID;
> 
> static ?
> 
> > +
> > +static u16 mm_sp_id;
> > +
> > +#endif
> > +
> >  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
> >  static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
> >  static efi_uintn_t max_payload_size;	/* func + data */
> > @@ -24,6 +56,7 @@ struct mm_connection {
> >  	u32 session;
> >  };
> >  
> > +#if (IS_ENABLED(CONFIG_OPTEE))
> >  /**
> >   * get_connection() - Retrieve OP-TEE session for a specific UUID.
> >   *
> > @@ -143,13 +176,224 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
> >  
> >  	return ret;
> >  }
> > +#endif
> > +
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +
> > +/**
> > + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> > + *
> > + * Notifies the MM partition in the trusted world that
> > + * data is available in the shared buffer.
> > + * This is a blocking call during which trusted world has exclusive access
> > + * to the MM shared buffer.
> > + *
> > + * Return:
> > + *
> > + * 0 on success
> > + */
> > +static int ffa_notify_mm_sp(void)
> > +{
> > +	struct ffa_send_direct_data msg = {0};
> > +	int ret;
> > +	int sp_event_ret = -1;
> > +
> > +	if (!ffa_bus_ops_get())
> > +		return -EINVAL;
> > +
> > +	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
> > +
> > +	ret = ffa_bus_ops_get()->sync_send_receive(mm_sp_id, &msg);
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	sp_event_ret = msg.data0; /* x3 */
> > +
> > +	if (sp_event_ret == MM_SUCCESS)
> > +		return 0;
> > +
> > +	/*
> > +	 * Failure to notify the MM SP
> > +	 */
> > +
> > +	return -EACCES;
> > +}
> >  
> >  /**
> > - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
> > + * ffa_discover_mm_sp_id() - Query the MM partition ID
> > + *
> > + * Use the FF-A driver to get the MM partition ID.
> > + * If multiple partitions are found, use the first one.
> > + * This is a boot time function.
> > + *
> > + * Return:
> > + *
> > + * 0 on success
> > + */
> > +static int ffa_discover_mm_sp_id(void)
> > +{
> > +	u32 count = 0, size = 0;
> > +	int ret;
> > +	struct ffa_partition_info *parts_info;
> > +
> > +	if (!ffa_bus_ops_get())
> > +		return -EINVAL;
> > +
> > +	/*
> > +	 * get from the driver the count of the SPs matching the UUID
> > +	 */
> > +	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &count, NULL);
> > +	if (ret != 0) {
> > +		log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	if (!count) {
> > +		log_info("EFI: No MM partition found\n");
> > +		return ret;
> > +	}
> > +
> > +	/*
> > +	 * pre-allocate a buffer to be filled by the driver
> > +	 * with	 ffa_partition_info structs
> > +	 */
> > +
> > +	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
> > +
> > +	parts_info = calloc(count, sizeof(struct ffa_partition_info));
> > +	if (!parts_info)
> > +		return -EINVAL;
> 
> -ENOMEM here is more accurate
> 
> > +
> > +	size = count * sizeof(struct ffa_partition_info);
> > +
> > +	/*
> > +	 * ask the driver to fill the
> > +	 * buffer with the SPs info
> > +	 */
> > +	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &size, parts_info);
> > +	if (ret != 0) {
> > +		log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret);
> > +		free(parts_info);
> > +		return ret;
> > +	}
> > +
> > +	/*
> > +	 * MM SPs found , use the first one
> > +	 */
> > +
> > +	mm_sp_id = parts_info[0].id;
> > +
> > +	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
> > +
> > +	free(parts_info);
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
> > + * @comm_buf:		locally allocated communication buffer used for rx/tx
> > + * @dsize:				communication buffer size
> > + *
> > + * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
> > + * that there is data to read from the shared buffer.
> > + * Communication with the MM SP is performed using FF-A transport.
> > + * On the event, MM SP can read the data from the buffer and
> > + * update the MM shared buffer with response data.
> > + * The response data is copied back to the communication buffer.
> > + *
> > + * Return:
> > + *
> > + * EFI status code
> > + */
> > +static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
> > +{
> > +	ulong tx_data_size;
> > +	int ffa_ret;
> > +	struct efi_mm_communicate_header *mm_hdr;
> > +	void *virt_shared_buf;
> > +
> > +	if (!comm_buf)
> > +		return EFI_INVALID_PARAMETER;
> > +
> > +	/* Discover MM partition ID at boot time */
> > +	if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
> > +		log_err("EFI: Failure to discover MM partition ID at boot time\n");
> > +		return EFI_UNSUPPORTED;
> > +	}
> > +
> > +	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> > +	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
> > +
> > +	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
> > +		return EFI_INVALID_PARAMETER;
> > +
> > +	/* Copy the data to the shared buffer */
> > +
> > +	virt_shared_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
> > +	memcpy(virt_shared_buf, comm_buf, tx_data_size);
> > +
> > +	/*
> > +	 * The secure world might have cache disabled for
> > +	 * the device region used for shared buffer (which is the case for Optee).
> > +	 * In this case, the secure world reads the data from DRAM.
> > +	 * Let's flush the cache so the DRAM is updated with the latest data.
> > +	 */
> > +	#ifdef CONFIG_ARM64
> > +	invalidate_dcache_all();
> 
> Is this only for arm64?

Yes, currently we only support Aarch64 which we currently need. Same done for the FF-A Linux kernel driver [1].
     
[1]: https://elixir.bootlin.com/linux/v6.1-rc3/source/drivers/firmware/arm_ffa/Kconfig#L5

> 
> > +	#endif
> > +
> > +	/* Announce there is data in the shared buffer */
> > +
> > +	ffa_ret = ffa_notify_mm_sp();
> > +	if (ffa_ret)
> > +		unmap_sysmem(virt_shared_buf);
> 
> This is a bit confusing handled in different places, can't we just move the
> check at the end of the switch cases and remote unmap_sysmem() from case 0?

Done in v7.

> 
> > +
> > +	switch (ffa_ret) {
> > +	case 0:
> > +	{
> > +		ulong rx_data_size;
> > +		/* Copy the MM SP response from the shared buffer to the communication buffer */
> > +		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> > +			sizeof(efi_guid_t) +
> > +			sizeof(size_t);
> > +
> > +		if (rx_data_size > comm_buf_size) {
> > +			unmap_sysmem(virt_shared_buf);
> > +			return EFI_OUT_OF_RESOURCES;
> > +		}
> > +
> > +		memcpy(comm_buf, virt_shared_buf, rx_data_size);
> > +		unmap_sysmem(virt_shared_buf);
> > +
> > +		return EFI_SUCCESS;
> > +	}
> > +	case -EINVAL:
> > +		return EFI_DEVICE_ERROR;
> > +	case -EPERM:
> > +		return EFI_INVALID_PARAMETER;
> > +	case -EACCES:
> > +		return EFI_ACCESS_DENIED;
> > +	case -EBUSY:
> > +		return EFI_OUT_OF_RESOURCES;
> > +	default:
> > +		return EFI_ACCESS_DENIED;
> > +	}
> > +}
> > +#endif
> > +
> > +/**
> > + * mm_communicate() - Adjust the communication buffer to the MM SP and send
> >   * it to OP-TEE
> >   *
> > - * @comm_buf:		locally allocted communcation buffer
> > + * @comm_buf:		locally allocated communication buffer
> >   * @dsize:		buffer size
> > + *
> > + * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
> > + * The comm_buf format is the same for both partitions.
> > + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> > + * When using the u-boot FF-A  driver, any MM SP is supported.
> > + *
> >   * Return:		status code
> >   */
> >  static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> > @@ -162,7 +406,12 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> >  	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> >  	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
> >  
> > -	ret = optee_mm_communicate(comm_buf, dsize);
> > +	ret = ffa_bus_discover();
> > +	if (ret != 0)
> > +		ret = optee_mm_communicate(comm_buf, dsize);
> > +	else
> > +		ret = ffa_mm_communicate(comm_buf, dsize);
> > +
> >  	if (ret != EFI_SUCCESS) {
> >  		log_err("%s failed!\n", __func__);
> >  		return ret;
> > @@ -258,6 +507,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
> >  		goto out;
> >  	}
> >  	*size = var_payload->size;
> > +
> > +	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
> > +			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
> > +				MM_VARIABLE_COMMUNICATE_SIZE;
> > +	#endif
> > +
> >  	/*
> >  	 * There seems to be a bug in EDK2 miscalculating the boundaries and
> >  	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> > @@ -697,7 +953,7 @@ void efi_variables_boot_exit_notify(void)
> >  		ret = EFI_NOT_FOUND;
> >  
> >  	if (ret != EFI_SUCCESS)
> > -		log_err("Unable to notify StMM for ExitBootServices\n");
> > +		log_err("Unable to notify the MM partition for ExitBootServices\n");
> >  	free(comm_buf);
> >  
> >  	/*
> > -- 
> > 2.17.1
> > 
> 
> Thanks
> /Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2022-10-24 12:13                                       ` Ilias Apalodimas
@ 2022-11-08 11:01                                         ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-08 11:01 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, nd

On Mon, Oct 24, 2022 at 03:13:08PM +0300, Ilias Apalodimas wrote:
> On Thu, Oct 13, 2022 at 11:38:57AM +0100, Abdellatif El Khlifi wrote:
> > turn on EFI MM communication
> > 
> > On corstone1000 platform MM communication between u-boot
> > and the secure world (Optee) is done using the FF-A bus.
> > 
> > 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>
> > 
> > ---
> > 
> > Changelog:
> > ===============
> > 
> > v6:
> > 
> > * corstone-1000: enable optee driver
> > * corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig
> > 
> > v4:
> > 
> > * corstone-1000: turn on EFI MM communication
> > 
> >  configs/corstone1000_defconfig | 4 ++++
> >  include/configs/corstone1000.h | 9 +++++++++
> >  2 files changed, 13 insertions(+)
> > 
> > diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
> > index ed2e0fe70a..4c9ed9fb71 100644
> > --- a/configs/corstone1000_defconfig
> > +++ b/configs/corstone1000_defconfig
> > @@ -52,3 +52,7 @@ CONFIG_DM_SERIAL=y
> >  CONFIG_USB=y
> >  CONFIG_USB_ISP1760=y
> >  CONFIG_ERRNO_STR=y
> > +CONFIG_EFI_MM_COMM_TEE=y
> > +CONFIG_TEE=y
> > +CONFIG_OPTEE=y
> > +CONFIG_ARM_FFA_TRANSPORT=y
> > diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
> > index 8e0230c135..997d0bebaf 100644
> > --- a/include/configs/corstone1000.h
> > +++ b/include/configs/corstone1000.h
> > @@ -14,6 +14,15 @@
> >  
> >  #include <linux/sizes.h>
> >  
> > +#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
> > +
> > +/*
> > + * shared buffer physical address used for communication between
> > + * u-boot and the MM SP
> > + */
> > +#define FFA_SHARED_MM_BUFFER_ADDR	(0x023F8000)
> > +#define FFA_SHARED_MM_BUFFER_OFFSET	(0)
> 
> The rest of the declarations on this file don't have () so please remove
> them.  Also is FFA_SHARED_MM_BUFFER_ADDR used anywhere that would justify UL
> in the suffix?

Done in v7.

> 
> Thanks
> /Ilias
> > +
> >  #define V2M_BASE		0x80000000
> >  
> >  #define CONFIG_PL011_CLOCK	50000000
> > -- 
> > 2.17.1
> > 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2022-10-24 14:19                                       ` Jens Wiklander
@ 2022-11-08 11:13                                         ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-08 11:13 UTC (permalink / raw)
  To: Jens Wiklander; +Cc: u-boot, nd

On Mon, Oct 24, 2022 at 04:19:18PM +0200, Jens Wiklander wrote:
> On Thu, Oct 13, 2022 at 11:38:48AM +0100, Abdellatif El Khlifi wrote:
> > add support for x0-x17 registers used by the SMC calls
> > 
> > In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
> > Results are returned in x0-x17.
> > 
> > This work is inspired from the following kernel commit:
> > 
> > arm64: smccc: Add support for SMCCCv1.2 extended input/output registers
> > 
> > [1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
> > 
> > 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>
> > 
> > ---
> > 
> > Changelog:
> > ===============
> > 
> > v4:
> > 
> > * rename the commit title and improve description
> >   new commit title: the current
> > 
> > v3:
> > 
> > * port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
> >   commit title:
> >       arm64: smccc: add Xn registers support used by SMC calls
> > 
> > arch/arm/cpu/armv8/smccc-call.S | 53 +++++++++++++++++++++++++++++++++
> >  arch/arm/lib/asm-offsets.c      | 14 +++++++++
> >  include/linux/arm-smccc.h       | 43 ++++++++++++++++++++++++++
> >  3 files changed, 110 insertions(+)
> > 
> > diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
> > index dc92b28777..ec6f299bc9 100644
> > --- a/arch/arm/cpu/armv8/smccc-call.S
> > +++ b/arch/arm/cpu/armv8/smccc-call.S
> > @@ -1,6 +1,8 @@
> >  /* SPDX-License-Identifier: GPL-2.0 */
> >  /*
> >   * Copyright (c) 2015, Linaro Limited
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  #include <linux/linkage.h>
> >  #include <linux/arm-smccc.h>
> > @@ -45,3 +47,54 @@ ENDPROC(__arm_smccc_smc)
> >  ENTRY(__arm_smccc_hvc)
> >  	SMCCC	hvc
> >  ENDPROC(__arm_smccc_hvc)
> > +
> > +#ifdef CONFIG_ARM64
> > +
> > +	.macro SMCCC_1_2 instr
> > +	/* Save `res` and free a GPR that won't be clobbered */
> > +	stp     x1, x19, [sp, #-16]!
> > +
> > +	/* Ensure `args` won't be clobbered while loading regs in next step */
> > +	mov	x19, x0
> > +
> > +	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
> > +	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
> > +	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
> > +	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
> > +	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
> > +	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
> > +	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
> > +	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
> > +	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
> > +	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
> > +
> > +	\instr #0
> > +
> > +	/* Load the `res` from the stack */
> > +	ldr	x19, [sp]
> > +
> > +	/* Store the registers x0 - x17 into the result structure */
> > +	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
> > +	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
> > +	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
> > +	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
> > +	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
> > +	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
> > +	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
> > +	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
> > +	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
> > +
> > +	/* Restore original x19 */
> > +	ldp     xzr, x19, [sp], #16
> > +	ret
> > +	.endm
> > +
> > +/*
> > + * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
> > + *			  struct arm_smccc_1_2_regs *res);
> > + */
> > +ENTRY(arm_smccc_1_2_smc)
> > +	SMCCC_1_2 smc
> > +ENDPROC(arm_smccc_1_2_smc)
> > +
> > +#endif
> > diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
> > index 22fd541f9a..1bc2d90faa 100644
> > --- a/arch/arm/lib/asm-offsets.c
> > +++ b/arch/arm/lib/asm-offsets.c
> > @@ -9,6 +9,9 @@
> >   * generate asm statements containing #defines,
> >   * compile this file to assembler, and then extract the
> >   * #defines from the assembly-language output.
> > + *
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  
> >  #include <common.h>
> > @@ -117,6 +120,17 @@ int main(void)
> >  	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
> >  	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
> >  	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
> > +	#ifdef CONFIG_ARM64
> > +		DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
> > +		DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
> > +		DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
> > +		DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
> > +		DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
> > +		DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
> > +		DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
> > +		DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
> > +		DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
> > +	#endif
> 
> We don't need another level of indentation here, please follow the
> established style in this file.
> 
> With that fixed please add
> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>

Thanks, done in v7.

> 
> Cheers,
> Jens
> 
> >  #endif
> >  
> >  	return 0;
> > diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> > index e1d09884a1..9105031d55 100644
> > --- a/include/linux/arm-smccc.h
> > +++ b/include/linux/arm-smccc.h
> > @@ -1,6 +1,8 @@
> >  /* SPDX-License-Identifier: GPL-2.0 */
> >  /*
> >   * Copyright (c) 2015, Linaro Limited
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  #ifndef __LINUX_ARM_SMCCC_H
> >  #define __LINUX_ARM_SMCCC_H
> > @@ -70,6 +72,47 @@ struct arm_smccc_res {
> >  	unsigned long a3;
> >  };
> >  
> > +#ifdef CONFIG_ARM64
> > +/**
> > + * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
> > + * @a0-a17 argument values from registers 0 to 17
> > + */
> > +struct arm_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;
> > +};
> > +
> > +/**
> > + * arm_smccc_1_2_smc() - make SMC calls
> > + * @args: arguments passed via struct arm_smccc_1_2_regs
> > + * @res: result values via struct arm_smccc_1_2_regs
> > + *
> > + * This function is used to make SMC calls following SMC Calling Convention
> > + * v1.2 or above. The content of the supplied param are copied from the
> > + * structure to registers prior to the SMC instruction. The return values
> > + * are updated with the content from registers on return from the SMC
> > + * instruction.
> > + */
> > +asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
> > +				  struct arm_smccc_1_2_regs *res);
> > +#endif
> > +
> >  /**
> >   * struct arm_smccc_quirk - Contains quirk information
> >   * @id: quirk identification
> > -- 
> > 2.17.1
> > 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v6 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-10-25  9:31                                       ` Jens Wiklander
  2022-10-25 10:27                                         ` Abdellatif El Khlifi
@ 2022-11-08 11:28                                         ` Abdellatif El Khlifi
  1 sibling, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-08 11:28 UTC (permalink / raw)
  To: Jens Wiklander; +Cc: u-boot, nd

On Tue, Oct 25, 2022 at 11:31:11AM +0200, Jens Wiklander wrote:
> On Thu, Oct 13, 2022 at 11:38:50AM +0100, Abdellatif El Khlifi wrote:
> > Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0
> > 
> > The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> > describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World leveraging TrustZone
> > technology.
> > 
> > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > querying the FF-A framework from the secure world.
> > 
> > 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> > and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> > 
> > In u-boot FF-A design, FF-A is considered as a discoverable bus.
> 
> U-Boot

All comments in this patch are addressed in v7, thanks.

> 
> > The Secure World is considered as one entity to communicate with
> > using the FF-A bus. FF-A communication is handled by one device and
> > one instance (the bus). This FF-A driver takes care of all the
> > interactions between Normal world and Secure World.
> > 
> > The driver exports its operations to be used by upper layers.
> > 
> > Exported operations:
> > 
> > - partition_info_get
> > - sync_send_receive
> > - rxtx_unmap
> > 
> > [1]: https://developer.arm.com/documentation/den0077/latest/
> > 
> > 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>
> > 
> > ---
> > 
> > Changelog:
> > ===============
> > 
> > v6:
> > 
> > * drop use of EFI runtime support (We decided with Linaro to add this later)
> > * drop discovery from initcalls (discovery will be on demand by FF-A users)
> > * set the alignment of the RX/TX buffers to the larger translation granule size
> > * move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
> > * update the documentation and move it to doc/arch/arm64.ffa.rst
> > 
> > v4:
> > 
> > * add doc/README.ffa.drv
> > * moving the FF-A driver work to drivers/firmware/arm-ffa
> > * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
> >   #if defined by #if CONFIG_IS_ENABLED
> > * improving error handling by mapping the FF-A errors to standard errors
> >   and logs
> > * replacing panics with an error log and returning an error code
> > * improving features discovery in FFA_FEATURES by introducing
> >   rxtx_min_pages private data field
> > * add ffa_remove and ffa_unbind functions
> > * improve how the driver behaves when bus discovery is done more than
> >   once
> > 
> > v3:
> > 
> > * align the interfaces of the u-boot FF-A driver with those in the linux
> >   FF-A driver
> > * remove the FF-A helper layer
> > * make the u-boot FF-A driver independent from EFI
> > * provide an optional config that enables copying the driver data to EFI
> >   runtime section at ExitBootServices service
> > * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
> > 
> > v2:
> > 
> > * make FF-A bus discoverable using device_{bind, probe} APIs
> > * remove device tree support
> > 
> > v1:
> > 
> > * introduce FF-A bus driver with device tree support
> > 
> >  MAINTAINERS                               |    7 +
> >  doc/arch/arm64.ffa.rst                    |  207 ++++
> >  doc/arch/index.rst                        |    1 +
> >  drivers/Kconfig                           |    2 +
> >  drivers/Makefile                          |    1 +
> >  drivers/firmware/arm-ffa/Kconfig          |   30 +
> >  drivers/firmware/arm-ffa/Makefile         |    6 +
> >  drivers/firmware/arm-ffa/arm-ffa-uclass.c |   16 +
> >  drivers/firmware/arm-ffa/arm_ffa_prv.h    |  196 +++
> >  drivers/firmware/arm-ffa/core.c           | 1337 +++++++++++++++++++++
> >  include/arm_ffa.h                         |   93 ++
> >  include/dm/uclass-id.h                    |    4 +
> >  12 files changed, 1900 insertions(+)
> >  create mode 100644 doc/arch/arm64.ffa.rst
> >  create mode 100644 drivers/firmware/arm-ffa/Kconfig
> >  create mode 100644 drivers/firmware/arm-ffa/Makefile
> >  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
> >  create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
> >  create mode 100644 drivers/firmware/arm-ffa/core.c
> >  create mode 100644 include/arm_ffa.h
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index a26b36c7c2..496f47a516 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -248,6 +248,13 @@ F:	drivers/net/cortina_ni.h
> >  F:	drivers/net/phy/ca_phy.c
> >  F:	configs/cortina_presidio-asic-pnand_defconfig
> >  
> > +ARM FF-A
> > +M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > +S:	Maintained
> > +F:	doc/arch/arm64.ffa.rst
> > +F:	drivers/firmware/arm-ffa/
> > +F:	include/arm_ffa.h
> > +
> >  ARM FREESCALE IMX
> >  M:	Stefano Babic <sbabic@denx.de>
> >  M:	Fabio Estevam <festevam@gmail.com>
> > diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> > new file mode 100644
> > index 0000000000..e98d2cf2b3
> > --- /dev/null
> > +++ b/doc/arch/arm64.ffa.rst
> > @@ -0,0 +1,207 @@
> > +.. SPDX-License-Identifier: GPL-2.0+
> > +
> > +Arm FF-A Driver
> > +===============
> > +
> > +Summary
> > +-------
> > +
> > +FF-A stands for Firmware Framework for Arm A-profile processors.
> > +
> > +FF-A specifies interfaces that enable a pair of software sandboxes to
> > +communicate with each other. A sandbox aka partition could
> > +be a VM in the Normal or Secure world, an application in S-EL0, or a
> > +Trusted OS in S-EL1.
> > +
> > +This FF-A driver implements the interfaces to communicate with partitions in
> > +the Secure world aka Secure partitions (SPs).
> > +
> > +The driver specifically focuses on communicating with SPs that isolate portions
> > +of EFI runtime services that must run in a protected environment which is
> > +inaccessible by the Host OS or Hypervisor. Examples of such services are
> > +set/get variables.
> > +
> > +FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> > +
> > +- Discover the presence of SPs of interest
> > +- Access an SP's service through communication protocols
> > +  e.g. EFI MM communication protocol
> > +
> > +FF-A and SMC specifications
> > +-------------------------------------------
> > +
> > +The current implementation of the driver relies on FF-A specification v1.0
> > +and uses SMC32 calling convention.
> > +
> > +At this stage we only need the FF-A v1.0 features.
> > +
> > +The driver has been tested with Optee OS which supports SMC32 for most of
> 
> s/Optee OS/OP-TEE/
> 
> > +the SMC ABIs.
> > +
> > +For more details please refer to the FF-A v1.0 spec:
> > +https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=
> > +
> > +Hypervisors are supported if they are configured to trap SMC calls.
> > +
> > +The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
> > +
> > +For more details please refer to the SMC Calling Convention v1.2 spec:
> > +https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
> > +
> > +Supported hardware
> > +--------------------------------
> > +
> > +Aarch64 plaforms
> > +
> > +Configuration
> > +----------------------
> > +
> > +CONFIG_ARM_FFA_TRANSPORT
> > +    Enables the FF-A bus driver. Turn this on if you want to use FF-A
> > +    communication.
> > +
> > +CONFIG_SANDBOX_FFA
> > +    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
> > +    Sandbox and provides functional tests for FF-A.
> > +
> > +FF-A ABIs under the hood
> > +---------------------------------------
> > +
> > +Invoking an FF-A ABI involves providing to the secure world/hypervisor the
> > +expected arguments from the ABI.
> > +
> > +The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction
> > +is executed.
> > +
> > +At the secure side level or hypervisor the ABI is handled at a higher exception
> > +level and the arguments are read and processed.
> > +
> > +The response is put back through x0 to x7 registers and control is given back
> > +to the U-boot FF-A driver (non-secure world).
> > +
> > +The driver reads the response and processes it accordingly.
> > +
> > +This methodology applies to all the FF-A ABIs in the driver.
> > +
> > +FF-A bus discovery in U-boot
> 
> U-Boot, please search and replace.
> 
> > +-------------------------------------------
> > +
> > +When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is discovered on
> > +demand by the clients (users).
> > +
> > +Clients can discover the FF-A bus using ffa_bus_discover() API which triggers the
> > +discovery process.
> > +
> > +ffa_bus_discover() creates, binds and probes the arm_ffa device using
> > +device_{bind, probe} APIs.
> > +
> > +The discovery process consists in communicating with secure world (or hypervisor)
> > +and querying specific data.
> > +
> > +The discovery process takes place during the arm_ffa device probing which is
> > +handled by ffa_probe().
> > +
> > +The FF-A bus discovery is successful and the bus is ready for use when these
> > +operations succeed:
> > +
> > +- querying the FF-A framework version
> > +- querying from secure world the U-boot endpoint ID
> > +- querying from secure world the RX/TX mapping  features
> > +- mapping the RX/TX buffers
> > +- querying from secure world all the partitions information
> > +
> > +Discovery failure results in a probing failure and the arm_ffa device is
> > +destroyed.
> > +
> > +Requirements for clients
> > +-------------------------------------
> > +
> > +When using the FF-A bus with EFI, clients must:
> > +
> > +- Query SPs in EFI boot time mode using the service UUID.
> > +- Unmap RX/TX buffers before EFI runtime mode starts.
> > +
> > +The RX/TX buffers are only available at EFI boot time. Querying partitions is
> > +done at boot time and data is cached for future use.
> > +
> > +RX/TX buffers should be unmapped by the user before EFI runtime mode
> > +starts. The driver provides a bus operation for that: rxtx_unmap()
> > +
> > +If  RX/TX buffers created by U-boot are not unmapped and by
> > +consequence becoming available at EFI runtime, secure world will get confused
> > +about RX/TX buffers ownership (U-boot vs kernel).
> > +
> > +The bus driver layer
> > +------------------------------
> > +
> > +The driver comes on top of the SMCCC layer and is implemented in
> > +drivers/firmware/arm-ffa/core.c
> > +
> > +The driver provides the following features:
> > +
> > +- Support for the 32-bit version of the following ABIs:
> > +
> > +FFA_VERSION
> > +FFA_ID_GET
> > +FFA_FEATURES
> > +FFA_PARTITION_INFO_GET
> > +FFA_RXTX_UNMAP
> > +FFA_RX_RELEASE
> > +FFA_RUN
> > +FFA_ERROR
> > +FFA_SUCCESS
> > +FFA_INTERRUPT
> > +
> > +- Support for the 64-bit version of the following ABIs:
> > +
> > +FFA_RXTX_MAP
> > +FFA_MSG_SEND_DIRECT_REQ
> > +FFA_MSG_SEND_DIRECT_RESP
> > +
> > +- Processing the received data from the secure world/hypervisor and caching it
> > +
> > +- Hiding from upper layers the FF-A protocol and registers details. Upper
> > +  layers focus on exchanged data, the driver takes care of how to transport
> > +  that to the secure world/hypervisor using FF-A
> > +
> > +- The driver provides callbacks to be used by clients to access the FF-A bus:
> > +
> > +partition_info_get
> > +sync_send_receive
> > +rxtx_unmap
> > +
> > +- FF-A bus discovery makes sure FF-A framework is responsive and compatible
> > +  with the driver
> > +
> > +- FF-A bus can be compiled and used without EFI
> > +
> > +Using armffa command
> > +-----------------------------------
> > +
> > +armffa is a command showcasing how to use the FF-A driver and how to invoke
> > +its operations.
> > +
> > +This provides a guidance to the client developers on how to call the FF-A bus
> > +interfaces.
> > +
> > +Usage:
> > +
> > +armffa <sub-command> <arguments>
> > +
> > +sub-commands:
> > +
> > +        getpart <partition UUID>
> > +
> > +            lists the partition(s) info
> > +
> > +        ping <partition ID>
> > +
> > +            sends a data pattern to the specified partition
> 
> It may be worth mentioning that this is an implementation defined
> command.
> 
> > +
> > +        devlist
> > +
> > +            displays the arm_ffa device info
> > +
> > +Contributors
> > +------------
> > +   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > diff --git a/doc/arch/index.rst b/doc/arch/index.rst
> > index 792d9182c3..8d1ab0ad4e 100644
> > --- a/doc/arch/index.rst
> > +++ b/doc/arch/index.rst
> > @@ -8,6 +8,7 @@ Architecture-specific doc
> >  
> >     arc
> >     arm64
> > +   arm64.ffa
> >     m68k
> >     mips
> >     nios2
> > diff --git a/drivers/Kconfig b/drivers/Kconfig
> > index 8b6fead351..b06b1ae481 100644
> > --- a/drivers/Kconfig
> > +++ b/drivers/Kconfig
> > @@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
> >  
> >  source "drivers/adc/Kconfig"
> >  
> > +source "drivers/firmware/arm-ffa/Kconfig"
> > +
> >  source "drivers/ata/Kconfig"
> >  
> >  source "drivers/axi/Kconfig"
> > diff --git a/drivers/Makefile b/drivers/Makefile
> > index 9d9f69a3c9..bf8d7b8cfc 100644
> > --- a/drivers/Makefile
> > +++ b/drivers/Makefile
> > @@ -111,6 +111,7 @@ obj-y += iommu/
> >  obj-y += smem/
> >  obj-y += thermal/
> >  obj-$(CONFIG_TEE) += tee/
> > +obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
> >  obj-y += axi/
> >  obj-y += ufs/
> >  obj-$(CONFIG_W1) += w1/
> > diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> > new file mode 100644
> > index 0000000000..f1427535f9
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/Kconfig
> > @@ -0,0 +1,30 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +config ARM_FFA_TRANSPORT
> > +	bool "Enable Arm Firmware Framework for Armv8-A driver"
> > +	depends on DM && ARM64
> > +	select ARM_SMCCC
> > +	select LIB_UUID
> > +	select DEVRES
> > +	help
> > +	  The Firmware Framework for Arm A-profile processors (FF-A)
> > +	  describes interfaces (ABIs) that standardize communication
> > +	  between the Secure World and Normal World leveraging TrustZone
> > +	  technology.
> > +
> > +	  This driver is based on FF-A specification v1.0 and uses SMC32
> > +	  calling convention.
> > +
> > +	  FF-A specification:
> > +
> > +	  https://developer.arm.com/documentation/den0077/a/?lang=en
> > +
> > +	  In u-boot FF-A design, FF-A is considered as a discoverable bus.
> 
> U-Boot
> 
> > +	  The Secure World is considered as one entity to communicate with
> > +	  using the FF-A bus.
> > +	  FF-A communication is handled by one device and one instance (the bus).
> > +	  This FF-A driver takes care of all the interactions between Normal world
> > +	  and Secure World.
> > +
> > +	  For more details about the FF-A driver, please refer to doc/README.ffa.drv
> 
> Not doc/arch/arm64.ffa.rst?
> 
> > +
> > diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
> > new file mode 100644
> > index 0000000000..043a8915be
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/Makefile
> > @@ -0,0 +1,6 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +#
> > +# (C) Copyright 2022
> > +# Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com.
> > +
> > +obj-y += arm-ffa-uclass.o core.o
> > diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> > new file mode 100644
> > index 0000000000..7d9695d289
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> > @@ -0,0 +1,16 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <asm/global_data.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +UCLASS_DRIVER(ffa) = {
> > +	.name		= "ffa",
> > +	.id		= UCLASS_FFA,
> > +};
> > diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> > new file mode 100644
> > index 0000000000..7bc90f7f66
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> > @@ -0,0 +1,196 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_PRV_H
> > +#define __ARM_FFA_PRV_H
> > +
> > +#include <arm_ffa.h>
> > +#include <linux/bitfield.h>
> > +#include <linux/bitops.h>
> > +#include <linux/arm-smccc.h>
> > +
> > +/*
> > + * This header is private. It is exclusively used by the FF-A driver
> > + */
> > +
> > +/* FF-A core driver name */
> > +#define FFA_DRV_NAME "arm_ffa"
> > +
> > +/* FF-A driver version definitions */
> > +
> > +#define MAJOR_VERSION_MASK		GENMASK(30, 16)
> > +#define MINOR_VERSION_MASK		GENMASK(15, 0)
> > +#define GET_FFA_MAJOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> > +#define GET_FFA_MINOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> > +#define PACK_VERSION_INFO(major, minor)			\
> > +	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
> > +	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> > +
> > +#define FFA_MAJOR_VERSION		(1)
> > +#define FFA_MINOR_VERSION		(0)
> > +#define FFA_VERSION_1_0		\
> > +			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> > +
> > +/* Endpoint ID mask (u-boot endpoint ID) */
> > +
> > +#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define GET_SELF_ENDPOINT_ID(x)		\
> > +			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> > +
> > +#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
> > +#define PREP_SELF_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> > +
> > +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> > +
> > +#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define PREP_PART_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> > +
> > +/*
> > + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> > + */
> > +
> > +#define FFA_SMC(calling_convention, func_num)				\
> > +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
> > +			   ARM_SMCCC_OWNER_STANDARD, (func_num))
> > +
> > +#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> > +#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
> > +
> > +enum ffa_abis {
> > +	FFA_ERROR					= 0x60,
> > +	FFA_SUCCESS					= 0x61,
> > +	FFA_INTERRUPT				= 0x62,
> > +	FFA_VERSION					= 0x63,
> > +	FFA_FEATURES				= 0x64,
> > +	FFA_RX_RELEASE				= 0x65,
> > +	FFA_RXTX_MAP				= 0x66,
> > +	FFA_RXTX_UNMAP			= 0x67,
> > +	FFA_PARTITION_INFO_GET		= 0x68,
> > +	FFA_ID_GET					= 0x69,
> > +	FFA_RUN						= 0x6D,
> > +	FFA_MSG_SEND_DIRECT_REQ	= 0x6F,
> > +	FFA_MSG_SEND_DIRECT_RESP	= 0x70,
> > +
> > +	/* to be updated when adding new FFA IDs */
> > +	FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
> > +	FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
> > +};
> > +
> > +/* number of the errors supported by the FF-A specification */
> > +#define MAX_NUMBER_FFA_ERR 9
> > +
> > +/* container structure and helper macros to map between an FF-A error and relevant error log */
> > +struct ffa_abi_errmap {
> > +	char *err_str[MAX_NUMBER_FFA_ERR];
> > +};
> > +
> > +#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
> > + *
> > + */
> > +struct ffa_partition_uuid {
> > +	u32 a1; /* w1 */
> > +	u32 a2; /* w2 */
> > +	u32 a3; /* w3 */
> > +	u32 a4; /* w4 */
> > +};
> > +
> > +/**
> > + * enum ffa_rxtx_buf_sizes - minimum sizes supported
> > + * for the RX/TX buffers
> > + */
> > +enum ffa_rxtx_buf_sizes {
> > +	RXTX_4K,
> > +	RXTX_64K,
> > +	RXTX_16K
> > +};
> > +
> > +/**
> > + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> > + * @rxbuf:	virtual address of the RX buffer
> > + * @txbuf:	virtual address of the TX buffer
> > + * @rxtx_min_pages:	RX/TX buffers minimum size in pages
> > + *
> > + * Data structure hosting the virtual addresses of the mapped RX/TX buffers
> > + * These addresses are used by the FF-A functions that use the RX/TX buffers
> > + */
> > +struct ffa_rxtxpair {
> > +	u64 rxbuf; /* virtual address */
> > +	u64 txbuf; /* virtual address */
> > +	size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
> > +};
> > +
> > +/**
> > + * struct ffa_partition_desc - the secure partition descriptor
> > + * @info:	partition information
> > + * @sp_uuid:	the secure partition UUID
> > + *
> > + * Each partition has its descriptor containing the partitions information and the UUID
> > + */
> > +struct ffa_partition_desc {
> > +	struct ffa_partition_info info;
> > +	struct ffa_partition_uuid sp_uuid;
> > +};
> > +
> > +/**
> > + * struct ffa_partitions - descriptors for all secure partitions
> > + * @count:	The number of partitions descriptors
> > + * @descs	The partitions descriptors table
> > + *
> > + * This data structure contains the partitions descriptors table
> > + */
> > +struct ffa_partitions {
> > +	u32 count;
> > +	struct ffa_partition_desc *descs; /* virtual address */
> > +};
> > +
> > +/**
> > + * struct ffa_prvdata - the driver private data structure
> > + *
> > + * @dev:	The arm_ffa device under u-boot driver model
> > + * @ffa_ops:	The driver operations structure
> > + * @fwk_version:	FF-A framework version
> > + * @id:	u-boot endpoint ID
> > + * @partitions:	The partitions descriptors structure
> > + * @pair:	The RX/TX buffers pair
> > + * @invoke_ffa_fn:	The function executing the FF-A function
> > + *
> > + * The driver data structure hosting all resident data.
> > + */
> > +struct ffa_prvdata {
> > +	struct udevice *dev;
> > +	struct ffa_bus_ops ffa_ops;
> > +	u32 fwk_version;
> > +	u16 id;
> > +	struct ffa_partitions partitions;
> > +	struct ffa_rxtxpair pair;
> > +	invoke_ffa_fn_t invoke_ffa_fn;
> > +};
> > +
> > +/**
> > + * ffa_device_get - create, bind and probe the arm_ffa device
> > + */
> > +int ffa_device_get(void);
> > +
> > +/**
> > + * ffa_bus_prvdata_get - bus driver private data getter
> > + */
> > +struct ffa_prvdata **ffa_bus_prvdata_get(void);
> > +
> > +#endif
> > diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
> > new file mode 100644
> > index 0000000000..324367d12b
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/core.c
> > @@ -0,0 +1,1337 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include "arm_ffa_prv.h"
> > +#include <asm/global_data.h>
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <dm/device-internal.h>
> > +#include <dm/devres.h>
> > +#include <dm/root.h>
> > +#include <linux/errno.h>
> > +#include <linux/sizes.h>
> > +#include <log.h>
> > +#include <malloc.h>
> > +#include <string.h>
> > +#include <uuid.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/**
> > + * The device private data structure containing all the
> > + * data read from secure world
> > + */
> > +struct ffa_prvdata *ffa_priv_data;
> > +
> > +/* Error mapping declarations */
> > +
> > +int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
> > +	0,
> > +	-EOPNOTSUPP,	/* NOT_SUPPORTED */
> > +	-EINVAL,	/* INVALID_PARAMETERS */
> > +	-ENOMEM,	/* NO_MEMORY */
> > +	-EBUSY,		/* BUSY */
> > +	-EINTR,		/* INTERRUPTED */
> > +	-EACCES,	/* DENIED */
> > +	-EAGAIN,	/* RETRY */
> > +	-ECANCELED,	/* ABORTED */
> > +};
> > +
> > +struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
> > +		{
> > +			"",
> 
> Shouldn't all these empty strings be NULL instead? Given that's that
> what you check for in ffa_print_error_log() below.
> 
> You could save a few lines by using designated initializers for only the
> used elements in err_str for each FF-A function ID.
> 
> > +			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
> > +			"", /* INVALID_PARAMETERS */
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"", /* DENIED */
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
> > +		{
> > +			"",
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +			"", /* INVALID_PARAMETERS */
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"", /* DENIED */
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
> > +		{
> > +			"",
> > +			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
> > +			"", /* INVALID_PARAMETERS */
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"", /* DENIED */
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
> > +		{
> > +			"",
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +			"INVALID_PARAMETERS: Unrecognized UUID",
> > +			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
> > +			"BUSY: RX buffer of the caller is not free",
> > +			"", /* INTERRUPTED */
> > +			"DENIED: Callee is not in a state to handle this request",
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
> > +			{
> > +			"",
> > +			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
> > +			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"", /* DENIED */
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
> > +			{
> > +			"",
> > +			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
> > +			"", /* INVALID_PARAMETERS */
> > +			"", /* NO_MEMORY */
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"DENIED: Caller did not have ownership of the RX buffer",
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
> > +			{
> > +			"",
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
> > +			"NO_MEMORY: Not enough memory",
> > +			"", /* BUSY */
> > +			"", /* INTERRUPTED */
> > +			"DENIED: Buffer pair already registered",
> > +			"", /* RETRY */
> > +			"", /* ABORTED */
> > +		},
> > +	},
> > +};
> > +
> > +/**
> > + * ffa_to_std_errno - convert FF-A error code to standard error code
> > + * @ffa_errno:	Error code returned by the FF-A ABI
> > + *
> > + * This function maps the given FF-A error code as specified
> > + * by the spec to a u-boot standard error code.
> > + *
> > + * Return:
> > + *
> > + * The standard error code on success. . Otherwise, failure
> > + */
> > +int ffa_to_std_errno(int ffa_errno)
> > +{
> > +	int err_idx = -ffa_errno;
> > +
> > +	/* map the FF-A error code to the standard u-boot error code */
> > +	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
> > +		return ffa_to_std_errmap[err_idx];
> > +	return -EINVAL;
> > +}
> > +
> > +/**
> > + * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
> > + * @ffa_id:	FF-A ABI ID
> > + * @ffa_errno:	Error code returned by the FF-A ABI
> > + *
> > + * This function maps the FF-A error code to the error log relevant to the
> > + * selected FF-A ABI. Then the error log is printed.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. . Otherwise, failure
> > + */
> > +int ffa_print_error_log(u32 ffa_id, int ffa_errno)
> > +{
> > +	int err_idx = -ffa_errno, abi_idx = 0;
> > +
> > +	/* map the FF-A error code to the corresponding error log */
> > +
> > +	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
> > +		return -EINVAL;
> > +
> > +	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
> > +		return -EINVAL;
> > +
> > +	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
> > +	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
> > +		return -EINVAL;
> > +
> > +	if (!err_msg_map[abi_idx].err_str || !err_msg_map[abi_idx].err_str[err_idx])
> 
> err_str can't be NULL since it's an array in the struct ffa_abi_errmap.
> 
> > +		return -EINVAL;
> > +
> > +	ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Driver core functions
> > + */
> > +
> > +/**
> > + * ffa_remove_device - removes the arm_ffa device
> > + * @dev:	the device to be removed
> > + *
> > + * This function makes sure the arm_ffa device is removed
> > + * No need to free the kmalloced data when the device is destroyed.
> > + * It's automatically done by devm management by
> > + * device_remove() -> device_free() -> devres_release_probe().
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_remove_device(struct udevice *dev)
> > +{
> > +	int ret;
> > +
> > +	if (!dev) {
> > +		ffa_err("no udevice found");
> > +		return -ENODEV;
> > +	}
> > +
> > +	ret = device_remove(dev, DM_REMOVE_NORMAL);
> > +	if (ret) {
> > +		ffa_err("unable to remove. err:%d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	ffa_info("device removed and freed");
> > +
> > +	ret = device_unbind(dev);
> > +	if (ret) {
> > +		ffa_err("unable to unbind. err:%d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	ffa_info("device unbound");
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_device_get - create, bind and probe the arm_ffa device
> > + *
> > + * This function makes sure the arm_ffa device is
> > + * created, bound to this driver, probed and ready to use.
> > + * Arm FF-A transport is implemented through a single u-boot
> > + * device managing the FF-A bus (arm_ffa).
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_device_get(void)
> > +{
> > +	int ret;
> > +	struct udevice *dev = NULL;
> > +
> > +	ret = device_bind(dm_root(),
> > +			  DM_DRIVER_GET(arm_ffa),
> > +			  FFA_DRV_NAME,
> > +			  NULL,
> > +			  ofnode_null(),
> > +			  &dev);
> 
> There's no need for separate lines for each argument, please fold up a bit.
> 
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* The FF-A bus discovery succeeds when probing is successful */
> > +	ret = device_probe(dev);
> > +	if (ret) {
> > +		ffa_err("arm_ffa device probing failed");
> > +		ffa_remove_device(dev);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_get_version - FFA_VERSION handler function
> > + *
> > + * This function implements FFA_VERSION FF-A function
> > + * to get from the secure world the FF-A framework version
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_version(void)
> > +{
> > +	u16 major, minor;
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_VERSION),
> > +			.a1 = FFA_VERSION_1_0
> 
> It's generally preferred to have comma after the last initializer too.
> 
> It could also be worth comparing with the style (alignment and folding
> up where possible) of the corresponding driver in the Linux kernel which
> I find a bit easier to read. However, checkpatch seems happy enough so I
> guess it's not a big deal.
> 
> I asked earlier why you're not supporting the latest version, 1.1, but
> you never answered that.
> 
> > +			}, &res);
> > +
> > +	ffa_errno = res.a0;
> > +	if (ffa_errno < 0) {
> > +		ffa_print_error_log(FFA_VERSION, ffa_errno);
> > +		return ffa_to_std_errno(ffa_errno);
> > +	}
> > +
> > +	major = GET_FFA_MAJOR_VERSION(res.a0);
> > +	minor = GET_FFA_MINOR_VERSION(res.a0);
> > +
> > +	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> > +		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
> > +		ffa_info("Versions are compatible ");
> > +
> > +		ffa_priv_data->fwk_version = res.a0;
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
> > +		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +	return -EPROTONOSUPPORT;
> > +}
> > +
> > +/**
> > + * ffa_get_endpoint_id - FFA_ID_GET handler function
> > + *
> > + * This function implements FFA_ID_GET FF-A function
> > + * to get from the secure world u-boot endpoint ID
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_endpoint_id(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_ID_GET)
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
> > +		ffa_info("endpoint ID is %u", ffa_priv_data->id);
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +
> > +	ffa_print_error_log(FFA_ID_GET, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
> > + * @prop_field: properties field obtained from FFA_FEATURES ABI
> > + *
> > + * This function sets the minimum number of pages
> > + *  in each of the RX/TX buffers in the private data structure
> > + *
> > + * Return:
> > + *
> > + * buf_4k_pages points to the returned number of pages
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
> > +{
> > +	if (!ffa_priv_data)
> > +		return -EINVAL;
> > +
> > +	switch (prop_field) {
> > +	case RXTX_4K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 1;
> > +		break;
> > +	case RXTX_16K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 4;
> > +		break;
> > +	case RXTX_64K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 16;
> > +		break;
> > +	default:
> > +		ffa_err("RX/TX buffer size not supported");
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
> > + *
> > + * This function implements FFA_FEATURES FF-A function
> > + * to retrieve the FFA_RXTX_MAP features
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_rxtx_map_features(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_FEATURES),
> > +			.a1 = FFA_SMC_64(FFA_RXTX_MAP)
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> > +		return ffa_set_rxtx_buffers_pages_cnt((u32)res.a2);
> 
> The cast isn't needed.
> 
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_FEATURES, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> > + *
> > + * This  function  frees the RX/TX buffers
> > + *
> > + */
> > +static void ffa_free_rxtx_buffers(void)
> > +{
> > +	ffa_info("Freeing RX/TX buffers");
> > +
> > +	if (ffa_priv_data->pair.rxbuf) {
> > +		free((void *)ffa_priv_data->pair.rxbuf);
> > +		ffa_priv_data->pair.rxbuf = 0;
> > +	}
> > +
> > +	if (ffa_priv_data->pair.txbuf) {
> > +		free((void *)ffa_priv_data->pair.txbuf);
> > +		ffa_priv_data->pair.txbuf = 0;
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
> > + *
> > + * This function is used by ffa_map_rxtx_buffers to allocate
> > + * the RX/TX buffers before mapping them. The allocated memory is physically
> > + * contiguous since memalign ends up calling malloc which allocates
> > + * contiguous memory in u-boot.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_alloc_rxtx_buffers(void)
> > +{
> > +	u64 bytes;
> > +
> > +	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
> > +		 ffa_priv_data->pair.rxtx_min_pages);
> > +
> > +	bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> > +
> > +	/*
> > +	 * The alignment of the RX and TX buffers must be equal
> > +	 * to the larger translation granule size
> > +	 */
> > +
> > +	ffa_priv_data->pair.rxbuf = (u64)memalign(bytes, bytes);
> > +	if (!ffa_priv_data->pair.rxbuf) {
> > +		ffa_err("failure to allocate RX buffer");
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
> > +
> > +	ffa_priv_data->pair.txbuf = (u64)memalign(bytes, bytes);
> > +	if (!ffa_priv_data->pair.txbuf) {
> > +		free((void *)ffa_priv_data->pair.rxbuf);
> > +		ffa_priv_data->pair.rxbuf = 0;
> > +		ffa_err("failure to allocate the TX buffer");
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
> > +
> > +	/*
> > +	 * make sure the buffers are cleared before use
> > +	 */
> > +	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
> > +	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> > + *
> > + * This function implements FFA_RXTX_MAP FF-A function
> > + * to map the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_map_rxtx_buffers(void)
> > +{
> > +	int ret;
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ret = ffa_alloc_rxtx_buffers();
> > +	if (ret)
> > +		return ret;
> > +
> > +	/*
> > +	 * we need to pass the physical addresses of the RX/TX buffers
> > +	 * in u-boot physical/virtual mapping is 1:1
> > +	 *no need to convert from virtual to physical
> 
> A space is missing after the '*'.
> 
> > +	 */
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
> > +			.a1 = ffa_priv_data->pair.txbuf,
> > +			.a2 = ffa_priv_data->pair.rxbuf,
> > +			.a3 = ffa_priv_data->pair.rxtx_min_pages,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_info("RX/TX buffers mapped");
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
> > +
> > +	ffa_free_rxtx_buffers();
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
> > + *
> > + * This function implements FFA_RXTX_UNMAP FF-A function
> > + * to unmap the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_unmap_rxtx_buffers(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
> > +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id)
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_free_rxtx_buffers();
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
> > + *
> > + * This function invokes FFA_RX_RELEASE FF-A function
> > + * to release the ownership of the RX buffer
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_release_rx_buffer(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RX_RELEASE)
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> > +		return 0;
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_uuid_are_identical - checks whether two given UUIDs are identical
> > + * @uuid1: first UUID
> > + * @uuid2: second UUID
> > + *
> > + * This function is used by ffa_read_partitions_info to search
> > + * for a UUID in the partitions descriptors table
> > + *
> > + * Return:
> > + *
> > + * 1 when UUIDs match. Otherwise, 0
> > + */
> > +int ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
> > +			   const struct ffa_partition_uuid *uuid2)
> 
> Would it make sense to use the bool type instead?
> 
> > +{
> > +	if (!uuid1 || !uuid2)
> > +		return 0;
> > +
> > +	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
> > +}
> > +
> > +/**
> > + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> > + *							and saves it in the private structure
> > + * @count: The number of partitions queried
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + *
> > + * This function reads the partitions information
> > + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> > + * data structure.
> > + *
> > + * Return:
> > + *
> > + * The private data structure is updated with the partition(s) information
> > + * 0 is returned on success. Otherwise, failure
> > + */
> > +static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
> > +{
> > +	if (!count) {
> > +		ffa_err("no partition detected");
> > +		return -ENODATA;
> > +	}
> > +
> > +	ffa_info("Reading partitions data from the RX buffer");
> > +
> > +	if (!part_uuid) {
> > +		/*
> > +		 * querying information of all partitions
> > +		 */
> > +		u64 buf_bytes;
> > +		u64 data_bytes;
> > +		u32 desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +
> > +		data_bytes = count * sizeof(struct ffa_partition_desc);
> > +
> > +		buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> > +
> > +		if (data_bytes > buf_bytes) {
> > +			ffa_err("partitions data size exceeds the RX buffer size:");
> > +			ffa_err("    sizes in bytes: data %llu , RX buffer %llu ",
> > +				data_bytes,
> > +				buf_bytes);
> > +
> > +			return -ENOMEM;
> > +		}
> > +
> > +		ffa_priv_data->partitions.descs = devm_kmalloc(ffa_priv_data->dev, data_bytes,
> > +							       __GFP_ZERO);
> > +		if (!ffa_priv_data->partitions.descs) {
> > +			ffa_err("cannot  allocate partitions data buffer");
> > +			return -ENOMEM;
> > +		}
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> > +
> > +		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
> > +			ffa_priv_data->partitions.descs[desc_idx].info =
> > +				parts_info[desc_idx];
> > +
> > +			ffa_info("Partition ID %x : info cached",
> > +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> > +		}
> > +
> > +		ffa_priv_data->partitions.count = count;
> > +
> > +		ffa_info("%d partition(s) found and cached", count);
> > +
> > +	} else {
> > +		u32 rx_desc_idx, cached_desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +		u8 desc_found;
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> > +
> > +		/*
> > +		 * search for the SP IDs read from the RX buffer
> > +		 * in the already cached SPs.
> > +		 * Update the UUID when ID found.
> > +		 */
> > +		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
> > +			desc_found = 0;
> > +
> > +			/*
> > +			 * search the current ID in the cached partitions
> > +			 */
> > +			for (cached_desc_idx = 0;
> > +			     cached_desc_idx < ffa_priv_data->partitions.count;
> > +			     cached_desc_idx++) {
> > +				/*
> > +				 * save the UUID
> > +				 */
> > +				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
> > +				    parts_info[rx_desc_idx].id) {
> > +					ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
> > +						*part_uuid;
> > +
> > +					desc_found = 1;
> > +					break;
> > +				}
> > +			}
> > +
> > +			if (!desc_found)
> > +				return -ENODATA;
> > +		}
> > +	}
> > +
> > +	return  0;
> > +}
> > +
> > +/**
> > + * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
> > + *
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + * @pcount: Pointer to the number of partitions variable filled when querying
> > + *
> > + * This function executes the FFA_PARTITION_INFO_GET
> > + * to query the partitions data. Then, it calls ffa_read_partitions_info
> > + * to save the data in the private data structure.
> > + *
> > + * After reading the data the RX buffer is released using ffa_release_rx_buffer
> > + *
> > + * Return:
> > + *
> > + * When part_uuid is NULL, all partitions data are retrieved from secure world
> > + * When part_uuid is non NULL, data for partitions matching the given UUID are
> > + * retrieved and the number of partitions is returned
> > + * 0 is returned on success. Otherwise, failure
> > + */
> > +static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
> > +				     u32 *pcount)
> > +{
> > +	struct ffa_partition_uuid query_uuid = {0};
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	/*
> > +	 * If a UUID is specified. Information for one or more
> > +	 * partitions in the system is queried. Otherwise, information
> > +	 * for all installed partitions is queried
> > +	 */
> > +
> > +	if (part_uuid) {
> > +		if (!pcount)
> > +			return -EINVAL;
> > +
> > +		query_uuid = *part_uuid;
> > +	} else if (pcount) {
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
> > +			.a1 = query_uuid.a1,
> > +			.a2 = query_uuid.a2,
> > +			.a3 = query_uuid.a3,
> > +			.a4 = query_uuid.a4
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		int ret;
> > +
> > +		/*
> > +		 * res.a2 contains the count of partition information descriptors
> > +		 * populated in the RX buffer
> > +		 */
> > +		if (res.a2) {
> > +			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
> > +			if (ret) {
> > +				ffa_err("failed to read partition(s) data , error (%d)", ret);
> > +				ffa_release_rx_buffer();
> > +				return -EINVAL;
> > +			}
> > +		}
> > +
> > +		/*
> > +		 * return the SP count (when querying using a UUID)
> > +		 */
> > +		if (pcount)
> > +			*pcount = (u32)res.a2;
> > +
> > +		/*
> > +		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
> > +		 * is assigned to the consumer (u-boot). So, we need to give
> > +		 * the ownership back to the SPM or hypervisor
> > +		 */
> > +		ret = ffa_release_rx_buffer();
> > +
> > +		return ret;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
> > + *
> > + * The passed arguments:
> > + * Mode 1: When getting from the driver the number of
> > + *	secure partitions:
> > + *	@uuid_str: pointer to the UUID string
> > + *	@parts_size: pointer to the variable that contains the number of partitions
> > + *			 The variable will be set by the driver
> > + *	@buffer: NULL
> > + *
> > + * Mode 2: When requesting the driver to return the
> > + *	partitions information:
> > + *	@uuid_str: pointer to the UUID string
> > + *	@parts_size: pointer to the size of the SPs information buffer in bytes
> > + *	@buffer: pointer to SPs information buffer
> > + *		(allocated by the client).
> > + *		The buffer will be filled by the driver
> > + *
> > + * This function queries the secure partition data from
> > + * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
> > + * FF-A function to query the partition information from secure world.
> > + *
> > + * A client of the FF-A driver should know the UUID of the service it wants to
> > + * access. It should use the UUID to request the FF-A driver to provide the
> > + * partition(s) information of the service. The FF-A driver uses
> > + * PARTITION_INFO_GET to obtain this information. This is implemented through
> > + * ffa_get_partitions_info function.
> > + * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
> > + * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
> > + * They are not saved (already done). We only update the UUID in the cached area.
> > + * This assumes that partitions data does not change in the secure world.
> > + * Otherwise u-boot will have an outdated partition data. The benefit of caching
> > + * the information in the FF-A driver is to accommodate discovery after
> > + * ExitBootServices().
> > + *
> > + * When invoked through a client request, ffa_get_partitions_info should be
> > + * called twice. First call is to get from the driver the number of secure
> > + * partitions (SPs) associated to a particular UUID.
> > + * Then, the caller (client) allocates the buffer to host the SPs data and
> > + * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
> > + * buffer.
> > + *
> > + * To achieve the mechanism described above, ffa_get_partitions_info uses the
> > + * following functions:
> > + *		ffa_read_partitions_info
> > + *		ffa_query_partitions_info
> > + *
> > + * Return:
> > + *
> > + * @parts_size: When pointing to the number of partitions variable, the number is
> > + * set by the driver.
> > + * When pointing to the partitions information buffer size, the buffer will be
> > + * filled by the driver.
> > + *
> > + * On success 0 is returned. Otherwise, failure
> > + */
> > +static int ffa_get_partitions_info(const char *uuid_str,
> > +				   u32 *parts_size, struct ffa_partition_info *buffer)
> > +{
> > +	/*
> > +	 * fill_data:
> > +	 * 0: return the SP count
> > +	 * 1: fill SP data and return it to the caller
> > +	 * -1: undefined mode
> > +	 */
> > +	int fill_data = -1;
> > +	u32 desc_idx, client_desc_idx;
> > +	struct ffa_partition_uuid part_uuid = {0};
> > +	u32 client_desc_max_cnt;
> > +	u32 parts_found = 0;
> > +
> > +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
> > +		ffa_err("no partition installed");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!uuid_str) {
> > +		ffa_err("no UUID provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!parts_size) {
> > +		ffa_err("no size/count provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (be_uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
> > +		ffa_err("invalid UUID");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!buffer) {
> > +		/* Mode 1: getting the number of secure partitions */
> > +
> > +		fill_data = 0;
> > +
> > +		ffa_info("Preparing for checking partitions count");
> > +
> > +	} else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
> > +		   !(*parts_size % sizeof(struct ffa_partition_info))) {
> > +		/* Mode 2: retrieving the partitions information */
> > +
> > +		fill_data = 1;
> > +
> > +		client_desc_idx = 0;
> > +
> > +		/*
> > +		 * number of empty descriptors preallocated by the caller
> > +		 */
> > +		client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
> > +
> > +		ffa_info("Preparing for filling partitions info");
> > +
> > +	} else {
> > +		ffa_err("invalid function arguments provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_info("Searching partitions using the provided UUID");
> > +
> > +	/*
> > +	 * search in the cached partitions
> > +	 */
> > +	for (desc_idx = 0;
> > +	     desc_idx < ffa_priv_data->partitions.count;
> > +	     desc_idx++) {
> > +		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
> > +					   &part_uuid)) {
> > +			ffa_info("Partition ID %x matches the provided UUID",
> > +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> > +
> > +			parts_found++;
> > +
> > +			if (fill_data) {
> > +				/*
> > +				 * trying to fill the partition info in the input buffer
> > +				 */
> > +
> > +				if (client_desc_idx < client_desc_max_cnt) {
> > +					buffer[client_desc_idx++] =
> > +						ffa_priv_data->partitions.descs[desc_idx].info;
> > +					continue;
> > +				}
> > +
> > +				ffa_err("failed to fill the current descriptor client buffer full");
> > +				return -ENOBUFS;
> > +			}
> > +		}
> > +	}
> > +
> > +	if (!parts_found) {
> > +		int ret;
> > +
> > +		ffa_info("No partition found. Querying framework ...");
> > +
> > +		ret = ffa_query_partitions_info(&part_uuid, &parts_found);
> > +
> > +		if (ret == 0) {
> > +			if (!fill_data) {
> > +				*parts_size = parts_found;
> > +
> > +				ffa_info("Number of partition(s) found matching the UUID: %d",
> > +					 parts_found);
> > +			} else {
> > +				/*
> > +				 * If SPs data detected, they are already in the private data
> > +				 * structure, retry searching SP data again to return them
> > +				 *  to the caller
> > +				 */
> > +				if (parts_found)
> > +					ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
> > +				else
> > +					ret = -ENODATA;
> > +			}
> > +		}
> > +
> > +		return ret;
> > +	}
> > +
> > +	/* partition(s) found */
> > +	if (!fill_data)
> > +		*parts_size = parts_found;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_cache_partitions_info - Queries and saves all secure partitions data
> > + *
> > + * This function invokes FFA_PARTITION_INFO_GET FF-A
> > + * function to query from secure world all partitions information.
> > + *
> > + * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
> > + * All installed partitions information are returned. We cache them in the
> > + * resident private data structure and we keep the UUID field empty
> > + * (in FF-A 1.0 UUID is not provided by the partition descriptor)
> > + *
> > + * This function is called at the device probing level.
> > + * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_cache_partitions_info(void)
> > +{
> > +	return ffa_query_partitions_info(NULL, NULL);
> > +}
> > +
> > +/**
> > + * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> > + * @dst_part_id: destination partition ID
> > + * @msg: pointer to the message data preallocated by the client (in/out)
> > + *
> > + * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * FF-A functions.
> > + *
> > + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> > + * The response from the secure partition is handled by reading the
> > + * FFA_MSG_SEND_DIRECT_RESP arguments.
> > + *
> > + * The maximum size of the data that can be exchanged is 40 bytes which is
> > + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> > + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
> > +		return -EINVAL;
> > +
> > +	/* No partition installed */
> > +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
> > +		return -ENODEV;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ),
> > +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
> > +				PREP_PART_ENDPOINT_ID(dst_part_id),
> > +			.a2 = 0,
> > +			.a3 = msg->data0,
> > +			.a4 = msg->data1,
> > +			.a5 = msg->data2,
> > +			.a6 = msg->data3,
> > +			.a7 = msg->data4,
> > +			}, &res);
> > +
> > +	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
> > +		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RUN),
> > +			.a1 = res.a1
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		/* Message sent with no response */
> > +		return 0;
> > +	}
> > +
> > +	if (res.a0 == FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP)) {
> > +		/*
> > +		 * Message sent with response
> > +		 * extract the return data
> > +		 */
> > +		msg->data0 = res.a3;
> > +		msg->data1 = res.a4;
> > +		msg->data2 = res.a5;
> > +		msg->data3 = res.a6;
> > +		msg->data4 = res.a7;
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * __arm_ffa_fn_smc - 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 low level SMC assembly function
> > + *
> > + * Return: void
> > + */
> > +void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
> > +{
> > +	arm_smccc_1_2_smc(&args, res);
> > +}
> > +
> > +/**
> > + * ffa_set_smc_conduit - Set the SMC conduit
> > + *
> > + * This function selects the SMC conduit by setting the driver invoke function
> > + * to SMC assembly function
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_set_smc_conduit(void)
> > +{
> > +	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
> > +
> > +	if (!ffa_priv_data->invoke_ffa_fn) {
> > +		ffa_err("failure to set the invoke function");
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_info("Conduit is SMC");
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_set_bus_ops - Set the bus driver operations
> > + *
> > + * Setting the driver callbacks.
> > + *
> > + */
> > +static void ffa_set_bus_ops(void)
> > +{
> > +	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
> > +	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
> > +	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
> > +}
> > +
> > +/**
> > + * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
> > + * @dev:	the arm_ffa device
> > + *
> > + * This function creates the main data structure embedding all the driver data.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_alloc_prvdata(struct udevice *dev)
> > +{
> > +	if (!dev) {
> > +		ffa_err("no udevice found");
> > +		return -ENODEV;
> > +	}
> > +
> > +	/* The device is registered with the DM. Let's create the driver main data structure*/
> > +
> > +	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
> > +	if (!ffa_priv_data) {
> > +		ffa_err("can not allocate the driver main data structure");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	ffa_priv_data->dev = dev;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_probe - The driver probe function
> > + * @dev:	the arm_ffa device
> > + *
> > + * Probing is done at boot time and triggered by the uclass device discovery.
> > + * At probe level the following actions are done:
> > + *	- setting the conduit
> > + *	- querying the FF-A framework version
> > + *	- querying from secure world the u-boot endpoint ID
> > + *	- querying from secure world the supported features of FFA_RXTX_MAP
> > + *	- mapping the RX/TX buffers
> > + *	- querying from secure world all the partitions information
> > + *
> > + * All data queried from secure world is saved in the resident private data structure.
> > + *
> > + * The probe will fail if either FF-A framework is not detected or the
> > + * FF-A requests are not behaving correctly. This ensures that the
> > + * driver is not installed and its operations are not exported to the clients.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_probe(struct udevice *dev)
> > +{
> > +	int ret;
> > +
> > +	ret = ffa_alloc_prvdata(dev);
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ffa_set_bus_ops();
> > +
> > +	ret = ffa_set_smc_conduit();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_version();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_endpoint_id();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_rxtx_map_features();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_map_rxtx_buffers();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_cache_partitions_info();
> 
> I've asked this before, but never got an answer:
> Why are we saving all the found partitions in a cache? It seems that
> FFA_PARTITION_INFO_GET could be called each time when needed instead
> without any noticeable overhead. Or is the result cached for some other
> reason?
> 
> Cheers,
> Jens
> 
> > +	if (ret != 0) {
> > +		ffa_free_rxtx_buffers();
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_remove - The driver remove function
> > + * @dev:	the arm_ffa device
> > + * When the device is about to be removed ,  unmap the RX/TX buffers and free the memory
> > + * Return:
> > + *
> > + * 0 on success.
> > + */
> > +static int ffa_remove(struct udevice *dev)
> > +{
> > +	ffa_info("removing the device");
> > +
> > +	ffa_unmap_rxtx_buffers();
> > +
> > +	if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
> > +		ffa_free_rxtx_buffers();
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_unbind - The driver unbind function
> > + * @dev:	the arm_ffa device
> > + * After the device is removed and memory freed the device is unbound
> > + * Return:
> > + *
> > + * 0 on success.
> > + */
> > +static int ffa_unbind(struct udevice *dev)
> > +{
> > +	ffa_info("unbinding the device , private data already released");
> > +
> > +	ffa_priv_data = NULL;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_bus_ops_get - bus driver operations getter
> > + *
> > + * Return:
> > + * This function returns a pointer to the driver operations structure
> > + */
> > +const struct ffa_bus_ops *ffa_bus_ops_get(void)
> > +{
> > +	return &ffa_priv_data->ffa_ops;
> > +}
> > +
> > +/**
> > + * ffa_bus_prvdata_get - bus driver private data getter
> > + *
> > + * Return:
> > + * This function returns a pointer to the main private data structure
> > + */
> > +struct ffa_prvdata **ffa_bus_prvdata_get(void)
> > +{
> > +	return &ffa_priv_data;
> > +}
> > +
> > +/**
> > + * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
> > + *
> > + * 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 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.
> > + * All FF-A clients should use the arm_ffa device to use the FF-A transport.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_bus_discover(void)
> > +{
> > +	int ret = 0;
> > +
> > +	if (!ffa_priv_data)
> > +		ret = ffa_device_get();
> > +
> > +	return ret;
> > +}
> > +
> > +/**
> > + * Declaring the arm_ffa driver under UCLASS_FFA
> > + */
> > +
> > +U_BOOT_DRIVER(arm_ffa) = {
> > +	.name		= FFA_DRV_NAME,
> > +	.id		= UCLASS_FFA,
> > +	.probe		= ffa_probe,
> > +	.remove		= ffa_remove,
> > +	.unbind		= ffa_unbind,
> > +};
> > diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> > new file mode 100644
> > index 0000000000..d146e7b328
> > --- /dev/null
> > +++ b/include/arm_ffa.h
> > @@ -0,0 +1,93 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_H
> > +#define __ARM_FFA_H
> > +
> > +#include <linux/printk.h>
> > +
> > +/*
> > + * This header is public. It can be used by clients to access
> > + * data structures and definitions they need
> > + */
> > +
> > +/*
> > + * Macros for displaying logs
> > + */
> > +
> > +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +
> > +/*
> > + * struct ffa_partition_info - Partition information descriptor
> > + * @id:	Partition ID
> > + * @exec_ctxt:	Execution context count
> > + * @properties:	Partition properties
> > + *
> > + * Data structure containing information about partitions instantiated in the system
> > + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> > + */
> > +struct  __packed ffa_partition_info {
> > +	u16 id;
> > +	u16 exec_ctxt;
> > +/* partition supports receipt of direct requests */
> > +#define FFA_PARTITION_DIRECT_RECV	BIT(0)
> > +/* partition can send direct requests. */
> > +#define FFA_PARTITION_DIRECT_SEND	BIT(1)
> > +/* partition can send and receive indirect messages. */
> > +#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
> > +	u32 properties;
> > +};
> > +
> > +/*
> > + * struct ffa_send_direct_data - Data structure hosting the data
> > + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * @data0-4:	Data read/written from/to x3-x7 registers
> > + *
> > + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> > + * or read from FFA_MSG_SEND_DIRECT_RESP
> > + */
> > +
> > +/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
> > +struct __packed ffa_send_direct_data {
> > +	unsigned long data0; /* w3/x3 */
> > +	unsigned long data1; /* w4/x4 */
> > +	unsigned long data2; /* w5/x5 */
> > +	unsigned long data3; /* w6/x6 */
> > +	unsigned long data4; /* w7/x7 */
> > +};
> > +
> > +/**
> > + * struct ffa_bus_ops - The driver operations structure
> > + * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
> > + * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
> > + * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
> > + *
> > + * The data structure providing all the operations supported by the driver.
> > + * This structure is EFI runtime resident.
> > + */
> > +struct ffa_bus_ops {
> > +	int (*partition_info_get)(const char *uuid_str,
> > +				  u32 *parts_size, struct ffa_partition_info *buffer);
> > +	int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg);
> > +	int (*rxtx_unmap)(void);
> > +};
> > +
> > +/**
> > + * The device driver and the Uclass driver public functions
> > + */
> > +
> > +/**
> > + * ffa_bus_ops_get - driver operations getter
> > + */
> > +const struct ffa_bus_ops *ffa_bus_ops_get(void);
> > +
> > +/**
> > + * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
> > + */
> > +int ffa_bus_discover(void);
> > +
> > +#endif
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index a432e43871..5dd698b7a9 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -4,6 +4,9 @@
> >   *
> >   * (C) Copyright 2012
> >   * Pavel Herrmann <morpheus.ibis@gmail.com>
> > + *
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  
> >  #ifndef _DM_UCLASS_ID_H
> > @@ -55,6 +58,7 @@ enum uclass_id {
> >  	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
> >  	UCLASS_ETH,		/* Ethernet device */
> >  	UCLASS_ETH_PHY,		/* Ethernet PHY device */
> > +	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
> >  	UCLASS_FIRMWARE,	/* Firmware */
> >  	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
> >  	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
> > -- 
> > 2.17.1
> > 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v7 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2022-11-07 19:20                                       ` [PATCH v7 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2022-11-08 13:47                                         ` Ilias Apalodimas
  2022-11-11 12:32                                           ` Abdellatif El Khlifi
  2022-11-11 17:02                                         ` Anders Dellien
  1 sibling, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2022-11-08 13:47 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, jens.wiklander, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong

Hi Abdellatif,

On Mon, Nov 07, 2022 at 07:20:47PM +0000, Abdellatif El Khlifi wrote:
> convert UUID string to little endian binary data
> 
> 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>
> 
> ---
> 
> Changelog:
> ===============
> 
> v7:
> 
> * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> * make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
>   by using same APIs
> 
> v4:
> 
> * rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
>   a standalone commit (the current)
> 
> v3:
> 
> * introduce ffa_uuid_str_to_bin (provided by
>   arm_ffa: introduce Arm FF-A low-level driver)
> 
> include/uuid.h |  8 ++++++++
>  lib/uuid.c     | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 54 insertions(+)
> 
> diff --git a/include/uuid.h b/include/uuid.h
> index 4a4883d3b5..293a8eb0a5 100644
> --- a/include/uuid.h
> +++ b/include/uuid.h
> @@ -2,6 +2,8 @@
>  /*
>   * Copyright (C) 2014 Samsung Electronics
>   * Przemyslaw Marczak <p.marczak@samsung.com>
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  #ifndef __UUID_H__
>  #define __UUID_H__
> @@ -44,4 +46,10 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
>  const char *uuid_guid_get_str(const unsigned char *guid_bin);
>  void gen_rand_uuid(unsigned char *uuid_bin);
>  void gen_rand_uuid_str(char *uuid_str, int str_format);
> +
> +/**
> + * uuid_str_to_le_bin - Converts a UUID string to little endian binary data
> + */
> +int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
> +
>  #endif
> diff --git a/lib/uuid.c b/lib/uuid.c
> index 465e1ac38f..cde5ae2bb7 100644
> --- a/lib/uuid.c
> +++ b/lib/uuid.c
> @@ -1,6 +1,8 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  /*
>   * Copyright 2011 Calxeda, Inc.
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #include <common.h>
> @@ -346,6 +348,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
>  	return 0;
>  }
>  
> +/**
> + * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
> + * @uuid_str:	pointer to UUID string
> + * @uuid_bin:	pointer to allocated array for little endian output [16B]
> + *
> + * UUID string is 36 characters (36 bytes):
> + *
> + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
> + *
> + * where x is a hexadecimal character. Fields are separated by '-'s.
> + * When converting to a little endian binary UUID, the string fields are reversed.
> + *
> + * Return:
> + *
> + *    uuid_bin filled with little endian UUID data
> + *    On success 0 is returned. Otherwise, failure code.
> + */
> +int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
> +{
> +	u16 tmp16;
> +	u32 tmp32;
> +	u64 tmp64;
> +
> +	if (!uuid_str_valid(uuid_str) || !uuid_bin)
> +		return -EINVAL;
> +
> +	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
> +	memcpy(uuid_bin, &tmp32, 4);
> +
> +	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
> +	memcpy(uuid_bin + 4, &tmp16, 2);
> +
> +	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
> +	memcpy(uuid_bin + 6, &tmp16, 2);
> +
> +	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
> +	memcpy(uuid_bin + 8, &tmp16, 2);
> +
> +	tmp64 = cpu_to_le64(hextoul(uuid_str + 24, NULL));
> +	memcpy(uuid_bin + 10, (char *)&tmp64, 6);

The cast isn't needed here 

> +
> +	return 0;
> +}
> +
>  /*
>   * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
>   *
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v7 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-07 19:20                                       ` [PATCH v7 03/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
@ 2022-11-09 11:51                                         ` Jens Wiklander
  2022-11-11 14:36                                           ` Abdellatif El Khlifi
  2022-11-22 13:28                                           ` Abdellatif El Khlifi
  0 siblings, 2 replies; 478+ messages in thread
From: Jens Wiklander @ 2022-11-09 11:51 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong

On Mon, Nov 07, 2022 at 07:20:48PM +0000, Abdellatif El Khlifi wrote:
> Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0
> 
> The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World leveraging TrustZone
> technology.
> 
> This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> querying the FF-A framework from the secure world.
> 
> The driver uses SMC32 calling convention which means using the first
> 32-bit data of the Xn registers.
> 
> All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
> which has 64-bit version supported.
> 
> Both 32-bit and 64-bit direct messaging are supported which allows both
> 32-bit and 64-bit clients to use the FF-A bus.
> 
> In U-Boot FF-A design, FF-A is considered as a discoverable bus.
> The Secure World is considered as one entity to communicate with
> using the FF-A bus. FF-A communication is handled by one device and
> one instance (the bus). This FF-A driver takes care of all the
> interactions between Normal world and Secure World.
> 
> The driver exports its operations to be used by upper layers.
> 
> Exported operations:
> 
> - partition_info_get
> - sync_send_receive
> - rxtx_unmap
> 
> For more details please refer to the driver documentation [2].
> 
> [1]: https://developer.arm.com/documentation/den0077/latest/
> [2]: doc/arch/arm64.ffa.rst
> 
> 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>
> 
> ---
> 
> Changelog:
> ===============
> 
> v7:
> 
> * add support for 32-bit direct messaging
> * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> * improve the declaration of error handling mapping
> * stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported
> 
> v6:
> 
> * drop use of EFI runtime support (We decided with Linaro to add this later)
> * drop discovery from initcalls (discovery will be on demand by FF-A users)
> * set the alignment of the RX/TX buffers to the larger translation granule size
> * move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
> * update the documentation and move it to doc/arch/arm64.ffa.rst
> 
> v4:
> 
> * add doc/README.ffa.drv
> * moving the FF-A driver work to drivers/firmware/arm-ffa
> * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
>   #if defined by #if CONFIG_IS_ENABLED
> * improving error handling by mapping the FF-A errors to standard errors
>   and logs
> * replacing panics with an error log and returning an error code
> * improving features discovery in FFA_FEATURES by introducing
>   rxtx_min_pages private data field
> * add ffa_remove and ffa_unbind functions
> * improve how the driver behaves when bus discovery is done more than
>   once
> 
> v3:
> 
> * align the interfaces of the U-Boot FF-A driver with those in the linux
>   FF-A driver
> * remove the FF-A helper layer
> * make the U-Boot FF-A driver independent from EFI
> * provide an optional config that enables copying the driver data to EFI
>   runtime section at ExitBootServices service
> * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
> 
> v2:
> 
> * make FF-A bus discoverable using device_{bind, probe} APIs
> * remove device tree support
> 
> v1:
> 
> * introduce FF-A bus driver with device tree support
> 
> MAINTAINERS                               |    7 +
>  doc/arch/arm64.ffa.rst                    |  218 ++++
>  doc/arch/index.rst                        |    1 +
>  drivers/Kconfig                           |    2 +
>  drivers/Makefile                          |    1 +
>  drivers/firmware/arm-ffa/Kconfig          |   30 +
>  drivers/firmware/arm-ffa/Makefile         |    6 +
>  drivers/firmware/arm-ffa/arm-ffa-uclass.c |   16 +
>  drivers/firmware/arm-ffa/arm_ffa_prv.h    |  205 ++++
>  drivers/firmware/arm-ffa/core.c           | 1310 +++++++++++++++++++++
>  include/arm_ffa.h                         |   93 ++
>  include/dm/uclass-id.h                    |    4 +
>  12 files changed, 1893 insertions(+)
>  create mode 100644 doc/arch/arm64.ffa.rst
>  create mode 100644 drivers/firmware/arm-ffa/Kconfig
>  create mode 100644 drivers/firmware/arm-ffa/Makefile
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
>  create mode 100644 drivers/firmware/arm-ffa/core.c
>  create mode 100644 include/arm_ffa.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1cf99c1393..450b5725ce 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -263,6 +263,13 @@ F:	drivers/net/cortina_ni.h
>  F:	drivers/net/phy/ca_phy.c
>  F:	configs/cortina_presidio-asic-pnand_defconfig
>  
> +ARM FF-A
> +M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +S:	Maintained
> +F:	doc/arch/arm64.ffa.rst
> +F:	drivers/firmware/arm-ffa/
> +F:	include/arm_ffa.h
> +
>  ARM FREESCALE IMX
>  M:	Stefano Babic <sbabic@denx.de>
>  M:	Fabio Estevam <festevam@gmail.com>
> diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> new file mode 100644
> index 0000000000..dfcec82e45
> --- /dev/null
> +++ b/doc/arch/arm64.ffa.rst
> @@ -0,0 +1,218 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +
> +Arm FF-A Driver
> +===============
> +
> +Summary
> +-------
> +
> +FF-A stands for Firmware Framework for Arm A-profile processors.
> +
> +FF-A specifies interfaces that enable a pair of software sandboxes to
> +communicate with each other. A sandbox aka partition could
> +be a VM in the Normal or Secure world, an application in S-EL0, or a
> +Trusted OS in S-EL1.
> +
> +This FF-A driver implements the interfaces to communicate with partitions in
> +the Secure world aka Secure partitions (SPs).
> +
> +The driver specifically focuses on communicating with SPs that isolate portions
> +of EFI runtime services that must run in a protected environment which is
> +inaccessible by the Host OS or Hypervisor. Examples of such services are
> +set/get variables.
> +
> +FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> +
> +- Discover the presence of SPs of interest
> +- Access an SP's service through communication protocols
> +  e.g. EFI MM communication protocol
> +
> +At this stage of development the FF-A driver supports EFI boot time only.
> +
> +Runtime support will be added in future developments.
> +
> +FF-A and SMC specifications
> +-------------------------------------------
> +
> +The current implementation of the driver relies on FF-A specification v1.0
> +and uses SMC32 calling convention which means using the first 32-bit data of the
> +Xn registers.
> +
> +At this stage we only need the FF-A v1.0 features.
> +
> +The driver has been tested with OP-TEE which supports SMC32 calling convention.
> +
> +For more details please refer to the FF-A v1.0 spec:
> +https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=
> +
> +Hypervisors are supported if they are configured to trap SMC calls.
> +
> +The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
> +
> +For more details please refer to the SMC Calling Convention v1.2 spec:
> +https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
> +
> +Supported hardware
> +--------------------------------
> +
> +Aarch64 plaforms
> +
> +Configuration
> +----------------------
> +
> +CONFIG_ARM_FFA_TRANSPORT
> +    Enables the FF-A bus driver. Turn this on if you want to use FF-A
> +    communication.
> +
> +CONFIG_SANDBOX_FFA
> +    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
> +    Sandbox and provides functional tests for FF-A.
> +
> +FF-A ABIs under the hood
> +---------------------------------------
> +
> +Invoking an FF-A ABI involves providing to the secure world/hypervisor the
> +expected arguments from the ABI.
> +
> +The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction
> +is executed.
> +
> +At the secure side level or hypervisor the ABI is handled at a higher exception
> +level and the arguments are read and processed.
> +
> +The response is put back through x0 to x7 registers and control is given back
> +to the U-Boot FF-A driver (non-secure world).
> +
> +The driver reads the response and processes it accordingly.
> +
> +This methodology applies to all the FF-A ABIs in the driver.
> +
> +FF-A bus discovery in U-Boot
> +-------------------------------------------
> +
> +When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is discovered on
> +demand by the clients (users).
> +
> +Clients can discover the FF-A bus using ffa_bus_discover() API which triggers the
> +discovery process.
> +
> +ffa_bus_discover() creates, binds and probes the arm_ffa device using
> +device_{bind, probe} APIs.
> +
> +The discovery process consists in communicating with secure world (or hypervisor)
> +and querying specific data.
> +
> +The discovery process takes place during the arm_ffa device probing which is
> +handled by ffa_probe().
> +
> +The FF-A bus discovery is successful and the bus is ready for use when these
> +operations succeed:
> +
> +- querying the FF-A framework version
> +- querying from secure world the U-Boot endpoint ID
> +- querying from secure world the RX/TX mapping  features
> +- mapping the RX/TX buffers
> +- querying from secure world all the partitions information
> +
> +Discovery failure results in a probing failure and the arm_ffa device is
> +destroyed.
> +
> +Requirements for clients
> +-------------------------------------
> +
> +When using the FF-A bus with EFI, clients must:
> +
> +- Query SPs in EFI boot time mode using the service UUID.
> +- Unmap RX/TX buffers before EFI runtime mode starts.
> +
> +The RX/TX buffers are only available at EFI boot time. Querying partitions is
> +done at boot time and data is cached for future use.
> +
> +RX/TX buffers should be unmapped by the user before EFI runtime mode
> +starts. The driver provides a bus operation for that: rxtx_unmap()
> +
> +If  RX/TX buffers created by U-Boot are not unmapped and by
> +consequence becoming available at EFI runtime, secure world will get confused
> +about RX/TX buffers ownership (U-Boot vs kernel).
> +
> +When invoking FF-A direct messaging, clients should specify which ABI protocol
> +they want to use (32-bit vs 64-bit). Selecting the protocol means using
> +the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> +The calling convention stays the same: SMC32.
> +
> +The bus driver layer
> +------------------------------
> +
> +The driver comes on top of the SMCCC layer and is implemented in
> +drivers/firmware/arm-ffa/core.c
> +
> +The driver provides the following features:
> +
> +- Support for the 32-bit version of the following ABIs:
> +
> +FFA_VERSION
> +FFA_ID_GET
> +FFA_FEATURES
> +FFA_PARTITION_INFO_GET
> +FFA_RXTX_UNMAP
> +FFA_RX_RELEASE
> +FFA_RUN
> +FFA_ERROR
> +FFA_SUCCESS
> +FFA_INTERRUPT
> +FFA_MSG_SEND_DIRECT_REQ
> +FFA_MSG_SEND_DIRECT_RESP
> +
> +- Support for the 64-bit version of the following ABIs:
> +
> +FFA_RXTX_MAP
> +FFA_MSG_SEND_DIRECT_REQ
> +FFA_MSG_SEND_DIRECT_RESP
> +
> +- Processing the received data from the secure world/hypervisor and caching it
> +
> +- Hiding from upper layers the FF-A protocol and registers details. Upper
> +  layers focus on exchanged data, the driver takes care of how to transport
> +  that to the secure world/hypervisor using FF-A
> +
> +- The driver provides callbacks to be used by clients to access the FF-A bus:
> +
> +partition_info_get
> +sync_send_receive
> +rxtx_unmap
> +
> +- FF-A bus discovery makes sure FF-A framework is responsive and compatible
> +  with the driver
> +
> +- FF-A bus can be compiled and used without EFI
> +
> +Using armffa command
> +-----------------------------------
> +
> +armffa is an implementation defined command showcasing how to use the FF-A driver and how to invoke
> +its operations.
> +
> +This provides a guidance to the client developers on how to call the FF-A bus
> +interfaces.
> +
> +Usage:
> +
> +armffa <sub-command> <arguments>
> +
> +sub-commands:
> +
> +        getpart <partition UUID>
> +
> +            lists the partition(s) info
> +
> +        ping <partition ID>
> +
> +            sends a data pattern to the specified partition
> +
> +        devlist
> +
> +            displays the arm_ffa device info
> +
> +Contributors
> +------------
> +   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> diff --git a/doc/arch/index.rst b/doc/arch/index.rst
> index 792d9182c3..8d1ab0ad4e 100644
> --- a/doc/arch/index.rst
> +++ b/doc/arch/index.rst
> @@ -8,6 +8,7 @@ Architecture-specific doc
>  
>     arc
>     arm64
> +   arm64.ffa
>     m68k
>     mips
>     nios2
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index 8b6fead351..b06b1ae481 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
>  
>  source "drivers/adc/Kconfig"
>  
> +source "drivers/firmware/arm-ffa/Kconfig"
> +
>  source "drivers/ata/Kconfig"
>  
>  source "drivers/axi/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index a1700c819d..b86c1d2a42 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -111,6 +111,7 @@ obj-y += iommu/
>  obj-y += smem/
>  obj-y += thermal/
>  obj-$(CONFIG_TEE) += tee/
> +obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
>  obj-y += axi/
>  obj-y += ufs/
>  obj-$(CONFIG_W1) += w1/
> diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> new file mode 100644
> index 0000000000..e4914b9bc7
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/Kconfig
> @@ -0,0 +1,30 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +config ARM_FFA_TRANSPORT
> +	bool "Enable Arm Firmware Framework for Armv8-A driver"
> +	depends on DM && ARM64
> +	select ARM_SMCCC
> +	select LIB_UUID
> +	select DEVRES
> +	help
> +	  The Firmware Framework for Arm A-profile processors (FF-A)
> +	  describes interfaces (ABIs) that standardize communication
> +	  between the Secure World and Normal World leveraging TrustZone
> +	  technology.
> +
> +	  This driver is based on FF-A specification v1.0 and uses SMC32
> +	  calling convention.
> +
> +	  FF-A specification:
> +
> +	  https://developer.arm.com/documentation/den0077/a/?lang=en
> +
> +	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
> +	  The Secure World is considered as one entity to communicate with
> +	  using the FF-A bus.
> +	  FF-A communication is handled by one device and one instance (the bus).
> +	  This FF-A driver takes care of all the interactions between Normal world
> +	  and Secure World.
> +
> +	  For more details about the FF-A driver, please refer to doc/arch/arm64.ffa.rst
> +
> diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
> new file mode 100644
> index 0000000000..043a8915be
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# (C) Copyright 2022
> +# Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com.
> +
> +obj-y += arm-ffa-uclass.o core.o
> diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> new file mode 100644
> index 0000000000..7d9695d289
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> @@ -0,0 +1,16 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <asm/global_data.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +UCLASS_DRIVER(ffa) = {
> +	.name		= "ffa",
> +	.id		= UCLASS_FFA,
> +};
> diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> new file mode 100644
> index 0000000000..ad7430ada9
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> @@ -0,0 +1,205 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#ifndef __ARM_FFA_PRV_H
> +#define __ARM_FFA_PRV_H
> +
> +#include <arm_ffa.h>
> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
> +#include <linux/arm-smccc.h>
> +
> +/*
> + * This header is private. It is exclusively used by the FF-A driver
> + */
> +
> +/* FF-A core driver name */
> +#define FFA_DRV_NAME "arm_ffa"
> +
> +/* FF-A driver version definitions */
> +
> +#define MAJOR_VERSION_MASK		GENMASK(30, 16)
> +#define MINOR_VERSION_MASK		GENMASK(15, 0)
> +#define GET_FFA_MAJOR_VERSION(x)		\
> +				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> +#define GET_FFA_MINOR_VERSION(x)		\
> +				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> +#define PACK_VERSION_INFO(major, minor)			\
> +	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
> +	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> +
> +#define FFA_MAJOR_VERSION		(1)
> +#define FFA_MINOR_VERSION		(0)
> +#define FFA_VERSION_1_0		\
> +			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> +
> +/* Endpoint ID mask (u-boot endpoint ID) */
> +
> +#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
> +#define GET_SELF_ENDPOINT_ID(x)		\
> +			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> +
> +#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
> +#define PREP_SELF_ENDPOINT_ID(x)		\
> +			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> +
> +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> +
> +#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
> +#define PREP_PART_ENDPOINT_ID(x)		\
> +			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> +
> +/*
> + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> + */
> +
> +#define FFA_SMC(calling_convention, func_num)				\
> +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
> +			   ARM_SMCCC_OWNER_STANDARD, (func_num))
> +
> +#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> +#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
> +
> +enum ffa_abis {
> +	FFA_ERROR					= 0x60,
> +	FFA_SUCCESS					= 0x61,
> +	FFA_INTERRUPT				= 0x62,
> +	FFA_VERSION					= 0x63,
> +	FFA_FEATURES				= 0x64,
> +	FFA_RX_RELEASE				= 0x65,
> +	FFA_RXTX_MAP				= 0x66,
> +	FFA_RXTX_UNMAP			= 0x67,
> +	FFA_PARTITION_INFO_GET		= 0x68,
> +	FFA_ID_GET					= 0x69,
> +	FFA_RUN						= 0x6D,
> +	FFA_MSG_SEND_DIRECT_REQ	= 0x6F,
> +	FFA_MSG_SEND_DIRECT_RESP	= 0x70,

Strange indentation above.

> +
> +	/* to be updated when adding new FFA IDs */
> +	FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
> +	FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
> +};
> +
> +enum ffa_abi_errcode {
> +	NOT_SUPPORTED = 1,
> +	INVALID_PARAMETERS,
> +	NO_MEMORY,
> +	BUSY,
> +	INTERRUPTED,
> +	DENIED,
> +	RETRY,
> +	ABORTED,
> +	MAX_NUMBER_FFA_ERR
> +};
> +
> +/* container structure and helper macros to map between an FF-A error and relevant error log */
> +struct ffa_abi_errmap {
> +	char *err_str[MAX_NUMBER_FFA_ERR];
> +};
> +
> +#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
> + *
> + */
> +struct ffa_partition_uuid {
> +	u32 a1; /* w1 */
> +	u32 a2; /* w2 */
> +	u32 a3; /* w3 */
> +	u32 a4; /* w4 */
> +};
> +
> +/**
> + * enum ffa_rxtx_buf_sizes - minimum sizes supported
> + * for the RX/TX buffers
> + */
> +enum ffa_rxtx_buf_sizes {
> +	RXTX_4K,
> +	RXTX_64K,
> +	RXTX_16K
> +};
> +
> +/**
> + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> + * @rxbuf:	virtual address of the RX buffer
> + * @txbuf:	virtual address of the TX buffer
> + * @rxtx_min_pages:	RX/TX buffers minimum size in pages
> + *
> + * Data structure hosting the virtual addresses of the mapped RX/TX buffers
> + * These addresses are used by the FF-A functions that use the RX/TX buffers
> + */
> +struct ffa_rxtxpair {
> +	u64 rxbuf; /* virtual address */
> +	u64 txbuf; /* virtual address */
> +	size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
> +};
> +
> +/**
> + * struct ffa_partition_desc - the secure partition descriptor
> + * @info:	partition information
> + * @sp_uuid:	the secure partition UUID
> + *
> + * Each partition has its descriptor containing the partitions information and the UUID
> + */
> +struct ffa_partition_desc {
> +	struct ffa_partition_info info;
> +	struct ffa_partition_uuid sp_uuid;
> +};
> +
> +/**
> + * struct ffa_partitions - descriptors for all secure partitions
> + * @count:	The number of partitions descriptors
> + * @descs	The partitions descriptors table
> + *
> + * This data structure contains the partitions descriptors table
> + */
> +struct ffa_partitions {
> +	u32 count;
> +	struct ffa_partition_desc *descs; /* virtual address */
> +};
> +
> +/**
> + * struct ffa_prvdata - the driver private data structure
> + *
> + * @dev:	The arm_ffa device under u-boot driver model
> + * @ffa_ops:	The driver operations structure
> + * @fwk_version:	FF-A framework version
> + * @id:	u-boot endpoint ID
> + * @partitions:	The partitions descriptors structure
> + * @pair:	The RX/TX buffers pair
> + * @invoke_ffa_fn:	The function executing the FF-A function
> + *
> + * The driver data structure hosting all resident data.
> + */
> +struct ffa_prvdata {
> +	struct udevice *dev;
> +	struct ffa_bus_ops ffa_ops;
> +	u32 fwk_version;
> +	u16 id;
> +	struct ffa_partitions partitions;
> +	struct ffa_rxtxpair pair;
> +	invoke_ffa_fn_t invoke_ffa_fn;
> +};
> +
> +/**
> + * ffa_device_get - create, bind and probe the arm_ffa device
> + */
> +int ffa_device_get(void);
> +
> +/**
> + * ffa_bus_prvdata_get - bus driver private data getter
> + */
> +struct ffa_prvdata **ffa_bus_prvdata_get(void);
> +
> +#endif
> diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
> new file mode 100644
> index 0000000000..b955e5187b
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/core.c
> @@ -0,0 +1,1310 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include "arm_ffa_prv.h"
> +#include <asm/global_data.h>
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/device-internal.h>
> +#include <dm/devres.h>
> +#include <dm/root.h>
> +#include <linux/errno.h>
> +#include <linux/sizes.h>
> +#include <log.h>
> +#include <malloc.h>
> +#include <string.h>
> +#include <uuid.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/**
> + * The device private data structure containing all the
> + * data read from secure world
> + */
> +struct ffa_prvdata *ffa_priv_data;
> +
> +/* Error mapping declarations */
> +
> +int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
> +	[NOT_SUPPORTED] = -EOPNOTSUPP,
> +	[INVALID_PARAMETERS] = -EINVAL,
> +	[NO_MEMORY] = -ENOMEM,
> +	[BUSY] = -EBUSY,
> +	[INTERRUPTED] = -EINTR,
> +	[DENIED] = -EACCES,
> +	[RETRY] = -EAGAIN,
> +	[ABORTED] = -ECANCELED,
> +};
> +
> +struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
> +	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
> +		{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
> +		{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
> +		{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
> +		{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> +			[INVALID_PARAMETERS] =
> +			"INVALID_PARAMETERS: Unrecognized UUID",
> +			[NO_MEMORY] =
> +			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
> +			[BUSY] =
> +			"BUSY: RX buffer of the caller is not free",
> +			[DENIED] =
> +			"DENIED: Callee is not in a state to handle this request",
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
> +			{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
> +			[INVALID_PARAMETERS] =
> +			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
> +			{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
> +			[DENIED] =
> +			"DENIED: Caller did not have ownership of the RX buffer",
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
> +			{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> +			[INVALID_PARAMETERS] =
> +			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
> +			[NO_MEMORY] =
> +			"NO_MEMORY: Not enough memory",
> +			[DENIED] =
> +			"DENIED: Buffer pair already registered",
> +		},
> +	},
> +};

Indentation above looks strange and inconsistent in some places. This
entire approach is in my opinion a bit complicated, no big deal, if no
one else complains I suppose it's OK.

> +
> +/**
> + * ffa_to_std_errno - convert FF-A error code to standard error code
> + * @ffa_errno:	Error code returned by the FF-A ABI
> + *
> + * This function maps the given FF-A error code as specified
> + * by the spec to a u-boot standard error code.
> + *
> + * Return:
> + *
> + * The standard error code on success. . Otherwise, failure
> + */
> +int ffa_to_std_errno(int ffa_errno)
> +{
> +	int err_idx = -ffa_errno;
> +
> +	/* map the FF-A error code to the standard u-boot error code */
> +	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
> +		return ffa_to_std_errmap[err_idx];
> +	return -EINVAL;
> +}
> +
> +/**
> + * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
> + * @ffa_id:	FF-A ABI ID
> + * @ffa_errno:	Error code returned by the FF-A ABI
> + *
> + * This function maps the FF-A error code to the error log relevant to the
> + * selected FF-A ABI. Then the error log is printed.
> + *
> + * Return:
> + *
> + * 0 on success. . Otherwise, failure
> + */
> +int ffa_print_error_log(u32 ffa_id, int ffa_errno)
> +{
> +	int err_idx = -ffa_errno, abi_idx = 0;
> +
> +	/* map the FF-A error code to the corresponding error log */
> +
> +	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
> +		return -EINVAL;
> +
> +	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
> +		return -EINVAL;
> +
> +	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
> +	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
> +		return -EINVAL;
> +
> +	if (!err_msg_map[abi_idx].err_str[err_idx])
> +		return -EINVAL;
> +
> +	ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
> +
> +	return 0;
> +}
> +
> +/*
> + * Driver core functions
> + */
> +
> +/**
> + * ffa_remove_device - removes the arm_ffa device
> + * @dev:	the device to be removed
> + *
> + * This function makes sure the arm_ffa device is removed
> + * No need to free the kmalloced data when the device is destroyed.
> + * It's automatically done by devm management by
> + * device_remove() -> device_free() -> devres_release_probe().
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_remove_device(struct udevice *dev)
> +{
> +	int ret;
> +
> +	if (!dev) {
> +		ffa_err("no udevice found");
> +		return -ENODEV;
> +	}
> +
> +	ret = device_remove(dev, DM_REMOVE_NORMAL);
> +	if (ret) {
> +		ffa_err("unable to remove. err:%d\n", ret);
> +		return ret;
> +	}
> +
> +	ffa_info("device removed and freed");
> +
> +	ret = device_unbind(dev);
> +	if (ret) {
> +		ffa_err("unable to unbind. err:%d\n", ret);
> +		return ret;
> +	}
> +
> +	ffa_info("device unbound");
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_device_get - create, bind and probe the arm_ffa device
> + *
> + * This function makes sure the arm_ffa device is
> + * created, bound to this driver, probed and ready to use.
> + * Arm FF-A transport is implemented through a single u-boot
> + * device managing the FF-A bus (arm_ffa).
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_device_get(void)
> +{
> +	int ret;
> +	struct udevice *dev = NULL;
> +
> +	ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> +			  &dev);
> +	if (ret)
> +		return ret;
> +
> +	/* The FF-A bus discovery succeeds when probing is successful */
> +	ret = device_probe(dev);
> +	if (ret) {
> +		ffa_err("arm_ffa device probing failed");
> +		ffa_remove_device(dev);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_get_version - FFA_VERSION handler function
> + *
> + * This function implements FFA_VERSION FF-A function
> + * to get from the secure world the FF-A framework version
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_get_version(void)
> +{
> +	u16 major, minor;
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
> +			}, &res);
> +
> +	ffa_errno = res.a0;
> +	if (ffa_errno < 0) {
> +		ffa_print_error_log(FFA_VERSION, ffa_errno);
> +		return ffa_to_std_errno(ffa_errno);
> +	}
> +
> +	major = GET_FFA_MAJOR_VERSION(res.a0);
> +	minor = GET_FFA_MINOR_VERSION(res.a0);
> +
> +	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> +		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> +
> +	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
> +		ffa_info("Versions are compatible ");
> +
> +		ffa_priv_data->fwk_version = res.a0;
> +
> +		return 0;
> +	}
> +
> +	ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
> +		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> +
> +	return -EPROTONOSUPPORT;
> +}
> +
> +/**
> + * ffa_get_endpoint_id - FFA_ID_GET handler function
> + *
> + * This function implements FFA_ID_GET FF-A function
> + * to get from the secure world u-boot endpoint ID
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_get_endpoint_id(void)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_ID_GET),
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
> +		ffa_info("endpoint ID is %u", ffa_priv_data->id);
> +
> +		return 0;
> +	}
> +
> +	ffa_errno = res.a2;
> +
> +	ffa_print_error_log(FFA_ID_GET, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
> + * @prop_field: properties field obtained from FFA_FEATURES ABI
> + *
> + * This function sets the minimum number of pages
> + *  in each of the RX/TX buffers in the private data structure
> + *
> + * Return:
> + *
> + * buf_4k_pages points to the returned number of pages
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
> +{
> +	if (!ffa_priv_data)
> +		return -EINVAL;
> +
> +	switch (prop_field) {
> +	case RXTX_4K:
> +		ffa_priv_data->pair.rxtx_min_pages = 1;
> +		break;
> +	case RXTX_16K:
> +		ffa_priv_data->pair.rxtx_min_pages = 4;
> +		break;
> +	case RXTX_64K:
> +		ffa_priv_data->pair.rxtx_min_pages = 16;
> +		break;
> +	default:
> +		ffa_err("RX/TX buffer size not supported");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
> + *
> + * This function implements FFA_FEATURES FF-A function
> + * to retrieve the FFA_RXTX_MAP features
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_get_rxtx_map_features(void)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_FEATURES),
> +			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> +		return ffa_set_rxtx_buffers_pages_cnt(res.a2);
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_FEATURES, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> + *
> + * This  function  frees the RX/TX buffers
> + *
> + */
> +static void ffa_free_rxtx_buffers(void)
> +{
> +	ffa_info("Freeing RX/TX buffers");
> +
> +	if (ffa_priv_data->pair.rxbuf) {
> +		free((void *)ffa_priv_data->pair.rxbuf);
> +		ffa_priv_data->pair.rxbuf = 0;
> +	}
> +
> +	if (ffa_priv_data->pair.txbuf) {
> +		free((void *)ffa_priv_data->pair.txbuf);
> +		ffa_priv_data->pair.txbuf = 0;
> +	}
> +}
> +
> +/**
> + * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
> + *
> + * This function is used by ffa_map_rxtx_buffers to allocate
> + * the RX/TX buffers before mapping them. The allocated memory is physically
> + * contiguous since memalign ends up calling malloc which allocates
> + * contiguous memory in u-boot.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_alloc_rxtx_buffers(void)
> +{
> +	u64 bytes;
> +
> +	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
> +		 ffa_priv_data->pair.rxtx_min_pages);
> +
> +	bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> +
> +	/*
> +	 * The alignment of the RX and TX buffers must be equal
> +	 * to the larger translation granule size
> +	 */
> +
> +	ffa_priv_data->pair.rxbuf = (u64)memalign(bytes, bytes);
> +	if (!ffa_priv_data->pair.rxbuf) {
> +		ffa_err("failure to allocate RX buffer");
> +		return -ENOBUFS;
> +	}
> +
> +	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
> +
> +	ffa_priv_data->pair.txbuf = (u64)memalign(bytes, bytes);
> +	if (!ffa_priv_data->pair.txbuf) {
> +		free((void *)ffa_priv_data->pair.rxbuf);
> +		ffa_priv_data->pair.rxbuf = 0;
> +		ffa_err("failure to allocate the TX buffer");
> +		return -ENOBUFS;
> +	}
> +
> +	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
> +
> +	/*
> +	 * make sure the buffers are cleared before use
> +	 */
> +	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
> +	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> + *
> + * This function implements FFA_RXTX_MAP FF-A function
> + * to map the RX/TX buffers
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_map_rxtx_buffers(void)
> +{
> +	int ret;
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ret = ffa_alloc_rxtx_buffers();
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * we need to pass the physical addresses of the RX/TX buffers
> +	 * in u-boot physical/virtual mapping is 1:1
> +	 * no need to convert from virtual to physical
> +	 */
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
> +			.a1 = ffa_priv_data->pair.txbuf,
> +			.a2 = ffa_priv_data->pair.rxbuf,
> +			.a3 = ffa_priv_data->pair.rxtx_min_pages,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		ffa_info("RX/TX buffers mapped");
> +		return 0;
> +	}
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
> +
> +	ffa_free_rxtx_buffers();
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
> + *
> + * This function implements FFA_RXTX_UNMAP FF-A function
> + * to unmap the RX/TX buffers
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_unmap_rxtx_buffers(void)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
> +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id),
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		ffa_free_rxtx_buffers();
> +		return 0;
> +	}
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
> + *
> + * This function invokes FFA_RX_RELEASE FF-A function
> + * to release the ownership of the RX buffer
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_release_rx_buffer(void)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> +		return 0;
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_uuid_are_identical - checks whether two given UUIDs are identical
> + * @uuid1: first UUID
> + * @uuid2: second UUID
> + *
> + * This function is used by ffa_read_partitions_info to search
> + * for a UUID in the partitions descriptors table
> + *
> + * Return:
> + *
> + * 1 when UUIDs match. Otherwise, 0
> + */
> +bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
> +			    const struct ffa_partition_uuid *uuid2)
> +{
> +	if (!uuid1 || !uuid2)
> +		return 0;
> +
> +	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
> +}
> +
> +/**
> + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> + *							and saves it in the private structure
> + * @count: The number of partitions queried
> + * @part_uuid: Pointer to the partition(s) UUID
> + *
> + * This function reads the partitions information
> + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> + * data structure.
> + *
> + * Return:
> + *
> + * The private data structure is updated with the partition(s) information
> + * 0 is returned on success. Otherwise, failure
> + */
> +static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
> +{
> +	if (!count) {
> +		ffa_err("no partition detected");
> +		return -ENODATA;
> +	}
> +
> +	ffa_info("Reading partitions data from the RX buffer");
> +
> +	if (!part_uuid) {
> +		/*
> +		 * querying information of all partitions
> +		 */
> +		u64 buf_bytes;
> +		u64 data_bytes;
> +		u32 desc_idx;
> +		struct ffa_partition_info *parts_info;
> +
> +		data_bytes = count * sizeof(struct ffa_partition_desc);
> +
> +		buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> +
> +		if (data_bytes > buf_bytes) {
> +			ffa_err("partitions data size exceeds the RX buffer size:");
> +			ffa_err("    sizes in bytes: data %llu , RX buffer %llu ",
> +				data_bytes,
> +				buf_bytes);
> +
> +			return -ENOMEM;
> +		}
> +
> +		ffa_priv_data->partitions.descs = devm_kmalloc(ffa_priv_data->dev, data_bytes,
> +							       __GFP_ZERO);
> +		if (!ffa_priv_data->partitions.descs) {
> +			ffa_err("cannot  allocate partitions data buffer");
> +			return -ENOMEM;
> +		}
> +
> +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> +
> +		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
> +			ffa_priv_data->partitions.descs[desc_idx].info =
> +				parts_info[desc_idx];
> +
> +			ffa_info("Partition ID %x : info cached",
> +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> +		}
> +
> +		ffa_priv_data->partitions.count = count;
> +
> +		ffa_info("%d partition(s) found and cached", count);
> +
> +	} else {
> +		u32 rx_desc_idx, cached_desc_idx;
> +		struct ffa_partition_info *parts_info;
> +		u8 desc_found;
> +
> +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> +
> +		/*
> +		 * search for the SP IDs read from the RX buffer
> +		 * in the already cached SPs.
> +		 * Update the UUID when ID found.
> +		 */
> +		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
> +			desc_found = 0;
> +
> +			/*
> +			 * search the current ID in the cached partitions
> +			 */
> +			for (cached_desc_idx = 0;
> +			     cached_desc_idx < ffa_priv_data->partitions.count;
> +			     cached_desc_idx++) {
> +				/*
> +				 * save the UUID
> +				 */
> +				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
> +				    parts_info[rx_desc_idx].id) {
> +					ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
> +						*part_uuid;
> +
> +					desc_found = 1;
> +					break;
> +				}
> +			}
> +
> +			if (!desc_found)
> +				return -ENODATA;
> +		}
> +	}
> +
> +	return  0;
> +}
> +
> +/**
> + * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
> + *
> + * @part_uuid: Pointer to the partition(s) UUID
> + * @pcount: Pointer to the number of partitions variable filled when querying
> + *
> + * This function executes the FFA_PARTITION_INFO_GET
> + * to query the partitions data. Then, it calls ffa_read_partitions_info
> + * to save the data in the private data structure.
> + *
> + * After reading the data the RX buffer is released using ffa_release_rx_buffer
> + *
> + * Return:
> + *
> + * When part_uuid is NULL, all partitions data are retrieved from secure world
> + * When part_uuid is non NULL, data for partitions matching the given UUID are
> + * retrieved and the number of partitions is returned
> + * 0 is returned on success. Otherwise, failure
> + */
> +static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
> +				     u32 *pcount)
> +{
> +	struct ffa_partition_uuid query_uuid = {0};
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	/*
> +	 * If a UUID is specified. Information for one or more
> +	 * partitions in the system is queried. Otherwise, information
> +	 * for all installed partitions is queried
> +	 */
> +
> +	if (part_uuid) {
> +		if (!pcount)
> +			return -EINVAL;
> +
> +		query_uuid = *part_uuid;
> +	} else if (pcount) {
> +		return -EINVAL;
> +	}
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
> +			.a1 = query_uuid.a1,
> +			.a2 = query_uuid.a2,
> +			.a3 = query_uuid.a3,
> +			.a4 = query_uuid.a4,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		int ret;
> +
> +		/*
> +		 * res.a2 contains the count of partition information descriptors
> +		 * populated in the RX buffer
> +		 */
> +		if (res.a2) {
> +			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
> +			if (ret) {
> +				ffa_err("failed to read partition(s) data , error (%d)", ret);
> +				ffa_release_rx_buffer();
> +				return -EINVAL;
> +			}
> +		}
> +
> +		/*
> +		 * return the SP count (when querying using a UUID)
> +		 */
> +		if (pcount)
> +			*pcount = (u32)res.a2;
> +
> +		/*
> +		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
> +		 * is assigned to the consumer (u-boot). So, we need to give
> +		 * the ownership back to the SPM or hypervisor
> +		 */
> +		ret = ffa_release_rx_buffer();
> +
> +		return ret;
> +	}
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
> + *
> + * The passed arguments:
> + * Mode 1: When getting from the driver the number of
> + *	secure partitions:
> + *	@uuid_str: pointer to the UUID string
> + *	@parts_size: pointer to the variable that contains the number of partitions
> + *			 The variable will be set by the driver
> + *	@buffer: NULL
> + *
> + * Mode 2: When requesting the driver to return the
> + *	partitions information:
> + *	@uuid_str: pointer to the UUID string
> + *	@parts_size: pointer to the size of the SPs information buffer in bytes
> + *	@buffer: pointer to SPs information buffer
> + *		(allocated by the client).
> + *		The buffer will be filled by the driver
> + *
> + * This function queries the secure partition data from
> + * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
> + * FF-A function to query the partition information from secure world.
> + *
> + * A client of the FF-A driver should know the UUID of the service it wants to
> + * access. It should use the UUID to request the FF-A driver to provide the
> + * partition(s) information of the service. The FF-A driver uses
> + * PARTITION_INFO_GET to obtain this information. This is implemented through
> + * ffa_get_partitions_info function.
> + * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
> + * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
> + * They are not saved (already done). We only update the UUID in the cached area.
> + * This assumes that partitions data does not change in the secure world.
> + * Otherwise u-boot will have an outdated partition data. The benefit of caching
> + * the information in the FF-A driver is to accommodate discovery after
> + * ExitBootServices().
> + *
> + * When invoked through a client request, ffa_get_partitions_info should be
> + * called twice. First call is to get from the driver the number of secure
> + * partitions (SPs) associated to a particular UUID.
> + * Then, the caller (client) allocates the buffer to host the SPs data and
> + * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
> + * buffer.
> + *
> + * To achieve the mechanism described above, ffa_get_partitions_info uses the
> + * following functions:
> + *		ffa_read_partitions_info
> + *		ffa_query_partitions_info
> + *
> + * Return:
> + *
> + * @parts_size: When pointing to the number of partitions variable, the number is
> + * set by the driver.
> + * When pointing to the partitions information buffer size, the buffer will be
> + * filled by the driver.

This is confusing, it's better if you use the same unit all the time.
Since you below require the size to be an even multiple of sizeof(struct
ffa_partition_info) you should perhaps use that unit.

> + *
> + * On success 0 is returned. Otherwise, failure
> + */
> +static int ffa_get_partitions_info(const char *uuid_str,
> +				   u32 *parts_size, struct ffa_partition_info *buffer)
> +{
> +	/*
> +	 * fill_data:
> +	 * 0: return the SP count
> +	 * 1: fill SP data and return it to the caller
> +	 * -1: undefined mode
> +	 */
> +	int fill_data = -1;

In the code below this is treated as a bool, it's never tested for -1,
so you could as well make this a bool.

> +	u32 desc_idx, client_desc_idx;
> +	struct ffa_partition_uuid part_uuid = {0};
> +	u32 client_desc_max_cnt;
> +	u32 parts_found = 0;
> +
> +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
> +		ffa_err("no partition installed");
> +		return -EINVAL;
> +	}
> +
> +	if (!uuid_str) {
> +		ffa_err("no UUID provided");
> +		return -EINVAL;
> +	}
> +
> +	if (!parts_size) {
> +		ffa_err("no size/count provided");
> +		return -EINVAL;
> +	}
> +
> +	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
> +		ffa_err("invalid UUID");
> +		return -EINVAL;
> +	}
> +
> +	if (!buffer) {
> +		/* Mode 1: getting the number of secure partitions */
> +
> +		fill_data = 0;
> +
> +		ffa_info("Preparing for checking partitions count");
> +
> +	} else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
> +		   !(*parts_size % sizeof(struct ffa_partition_info))) {
> +		/* Mode 2: retrieving the partitions information */
> +
> +		fill_data = 1;
> +
> +		client_desc_idx = 0;
> +
> +		/*
> +		 * number of empty descriptors preallocated by the caller
> +		 */
> +		client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
> +
> +		ffa_info("Preparing for filling partitions info");
> +
> +	} else {
> +		ffa_err("invalid function arguments provided");
> +		return -EINVAL;
> +	}
> +
> +	ffa_info("Searching partitions using the provided UUID");
> +
> +	/*
> +	 * search in the cached partitions
> +	 */
> +	for (desc_idx = 0;
> +	     desc_idx < ffa_priv_data->partitions.count;
> +	     desc_idx++) {
> +		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
> +					   &part_uuid)) {
> +			ffa_info("Partition ID %x matches the provided UUID",
> +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> +
> +			parts_found++;
> +
> +			if (fill_data) {
> +				/*
> +				 * trying to fill the partition info in the input buffer
> +				 */
> +
> +				if (client_desc_idx < client_desc_max_cnt) {
> +					buffer[client_desc_idx++] =
> +						ffa_priv_data->partitions.descs[desc_idx].info;
> +					continue;
> +				}
> +
> +				ffa_err("failed to fill the current descriptor client buffer full");
> +				return -ENOBUFS;
> +			}
> +		}
> +	}
> +
> +	if (!parts_found) {

By asking for a UUID never found ffa_query_partitions_info() will be
called again, even if the rx/tx buffers needed are not available any
longer. Since you populate the cache in ffa_probe() below, perhaps it
would be better to only rely on the cache after that point.

> +		int ret;
> +
> +		ffa_info("No partition found. Querying framework ...");
> +
> +		ret = ffa_query_partitions_info(&part_uuid, &parts_found);
> +
> +		if (ret == 0) {
> +			if (!fill_data) {
> +				*parts_size = parts_found;
> +
> +				ffa_info("Number of partition(s) found matching the UUID: %d",
> +					 parts_found);
> +			} else {
> +				/*
> +				 * If SPs data detected, they are already in the private data
> +				 * structure, retry searching SP data again to return them
> +				 *  to the caller
> +				 */
> +				if (parts_found)
> +					ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
> +				else
> +					ret = -ENODATA;
> +			}
> +		}
> +
> +		return ret;
> +	}
> +
> +	/* partition(s) found */
> +	if (!fill_data)
> +		*parts_size = parts_found;
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_cache_partitions_info - Queries and saves all secure partitions data
> + *
> + * This function invokes FFA_PARTITION_INFO_GET FF-A
> + * function to query from secure world all partitions information.
> + *
> + * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
> + * All installed partitions information are returned. We cache them in the
> + * resident private data structure and we keep the UUID field empty
> + * (in FF-A 1.0 UUID is not provided by the partition descriptor)
> + *
> + * This function is called at the device probing level.
> + * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_cache_partitions_info(void)
> +{
> +	return ffa_query_partitions_info(NULL, NULL);
> +}
> +
> +/**
> + * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> + * @dst_part_id: destination partition ID
> + * @msg: pointer to the message data preallocated by the client (in/out)
> + * @is_smc64: select 64-bit or 32-bit FF-A ABI
> + *
> + * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * FF-A functions.
> + *
> + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> + * The response from the secure partition is handled by reading the
> + * FFA_MSG_SEND_DIRECT_RESP arguments.
> + *
> + * The maximum size of the data that can be exchanged is 40 bytes which is
> + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg, bool is_smc64)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +	u64 req_mode, resp_mode;
> +
> +	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
> +		return -EINVAL;
> +
> +	/* No partition installed */
> +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
> +		return -ENODEV;

This check isn't needed. What if the partition ID is known by other
means?

> +
> +	if (is_smc64) {
> +		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
> +		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
> +	} else {
> +		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
> +		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
> +	}
> +
> +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = req_mode,
> +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
> +				PREP_PART_ENDPOINT_ID(dst_part_id),
> +			.a2 = 0,
> +			.a3 = msg->data0,
> +			.a4 = msg->data1,
> +			.a5 = msg->data2,
> +			.a6 = msg->data3,
> +			.a7 = msg->data4,
> +			}, &res);
> +
> +	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
> +		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_RUN),
> +			.a1 = res.a1,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		/* Message sent with no response */
> +		return 0;
> +	}
> +
> +	if (res.a0 == resp_mode) {
> +		/*
> +		 * Message sent with response
> +		 * extract the return data
> +		 */
> +		msg->data0 = res.a3;
> +		msg->data1 = res.a4;
> +		msg->data2 = res.a5;
> +		msg->data3 = res.a6;
> +		msg->data4 = res.a7;
> +
> +		return 0;
> +	}
> +
> +	ffa_errno = res.a2;
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * __arm_ffa_fn_smc - 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 low level SMC assembly function
> + *
> + * Return: void
> + */
> +void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
> +{
> +	arm_smccc_1_2_smc(&args, res);
> +}
> +
> +/**
> + * ffa_set_smc_conduit - Set the SMC conduit
> + *
> + * This function selects the SMC conduit by setting the driver invoke function
> + * to SMC assembly function
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_set_smc_conduit(void)
> +{
> +	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
> +
> +	if (!ffa_priv_data->invoke_ffa_fn) {
> +		ffa_err("failure to set the invoke function");
> +		return -EINVAL;
> +	}
> +
> +	ffa_info("Conduit is SMC");
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_set_bus_ops - Set the bus driver operations
> + *
> + * Setting the driver callbacks.
> + *
> + */
> +static void ffa_set_bus_ops(void)
> +{
> +	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
> +	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
> +	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
> +}
> +
> +/**
> + * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
> + * @dev:	the arm_ffa device
> + *
> + * This function creates the main data structure embedding all the driver data.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_alloc_prvdata(struct udevice *dev)
> +{
> +	if (!dev) {
> +		ffa_err("no udevice found");
> +		return -ENODEV;
> +	}
> +
> +	/* The device is registered with the DM. Let's create the driver main data structure*/
> +
> +	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
> +	if (!ffa_priv_data) {
> +		ffa_err("can not allocate the driver main data structure");
> +		return -ENOMEM;
> +	}
> +
> +	ffa_priv_data->dev = dev;
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_probe - The driver probe function
> + * @dev:	the arm_ffa device
> + *
> + * Probing is done at boot time and triggered by the uclass device discovery.
> + * At probe level the following actions are done:
> + *	- setting the conduit
> + *	- querying the FF-A framework version
> + *	- querying from secure world the u-boot endpoint ID
> + *	- querying from secure world the supported features of FFA_RXTX_MAP
> + *	- mapping the RX/TX buffers
> + *	- querying from secure world all the partitions information
> + *
> + * All data queried from secure world is saved in the resident private data structure.
> + *
> + * The probe will fail if either FF-A framework is not detected or the
> + * FF-A requests are not behaving correctly. This ensures that the
> + * driver is not installed and its operations are not exported to the clients.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_probe(struct udevice *dev)
> +{
> +	int ret;
> +
> +	ret = ffa_alloc_prvdata(dev);
> +	if (ret != 0)
> +		return ret;
> +
> +	ffa_set_bus_ops();
> +
> +	ret = ffa_set_smc_conduit();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_get_version();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_get_endpoint_id();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_get_rxtx_map_features();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_map_rxtx_buffers();
> +	if (ret != 0)
> +		return ret;
> +
> +	ret = ffa_cache_partitions_info();
> +	if (ret != 0) {
> +		ffa_free_rxtx_buffers();
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_remove - The driver remove function
> + * @dev:	the arm_ffa device
> + * When the device is about to be removed ,  unmap the RX/TX buffers and free the memory
> + * Return:
> + *
> + * 0 on success.
> + */
> +static int ffa_remove(struct udevice *dev)
> +{
> +	ffa_info("removing the device");
> +
> +	ffa_unmap_rxtx_buffers();
> +
> +	if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
> +		ffa_free_rxtx_buffers();
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_unbind - The driver unbind function
> + * @dev:	the arm_ffa device
> + * After the device is removed and memory freed the device is unbound
> + * Return:
> + *
> + * 0 on success.
> + */
> +static int ffa_unbind(struct udevice *dev)
> +{
> +	ffa_info("unbinding the device , private data already released");
> +
> +	ffa_priv_data = NULL;
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_bus_ops_get - bus driver operations getter
> + *
> + * Return:
> + * This function returns a pointer to the driver operations structure
> + */
> +const struct ffa_bus_ops *ffa_bus_ops_get(void)
> +{
> +	return &ffa_priv_data->ffa_ops;
> +}
> +
> +/**
> + * ffa_bus_prvdata_get - bus driver private data getter
> + *
> + * Return:
> + * This function returns a pointer to the main private data structure
> + */
> +struct ffa_prvdata **ffa_bus_prvdata_get(void)

Why a pointer to a pointer, isn't "struct ffa_prvdata *" enough?

> +{
> +	return &ffa_priv_data;
> +}
> +
> +/**
> + * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
> + *
> + * 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 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.
> + * All FF-A clients should use the arm_ffa device to use the FF-A transport.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_bus_discover(void)
> +{
> +	int ret = 0;
> +
> +	if (!ffa_priv_data)
> +		ret = ffa_device_get();
> +
> +	return ret;
> +}
> +
> +/**
> + * Declaring the arm_ffa driver under UCLASS_FFA
> + */
> +
> +U_BOOT_DRIVER(arm_ffa) = {
> +	.name		= FFA_DRV_NAME,
> +	.id		= UCLASS_FFA,
> +	.probe		= ffa_probe,
> +	.remove		= ffa_remove,
> +	.unbind		= ffa_unbind,
> +};
> diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> new file mode 100644
> index 0000000000..b0c8a18926
> --- /dev/null
> +++ b/include/arm_ffa.h
> @@ -0,0 +1,93 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#ifndef __ARM_FFA_H
> +#define __ARM_FFA_H
> +
> +#include <linux/printk.h>
> +
> +/*
> + * This header is public. It can be used by clients to access
> + * data structures and definitions they need
> + */
> +
> +/*
> + * Macros for displaying logs
> + */
> +
> +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> +
> +/*
> + * struct ffa_partition_info - Partition information descriptor
> + * @id:	Partition ID
> + * @exec_ctxt:	Execution context count
> + * @properties:	Partition properties
> + *
> + * Data structure containing information about partitions instantiated in the system
> + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> + */
> +struct  __packed ffa_partition_info {
> +	u16 id;
> +	u16 exec_ctxt;
> +/* partition supports receipt of direct requests */
> +#define FFA_PARTITION_DIRECT_RECV	BIT(0)
> +/* partition can send direct requests. */
> +#define FFA_PARTITION_DIRECT_SEND	BIT(1)
> +/* partition can send and receive indirect messages. */
> +#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
> +	u32 properties;
> +};

Perhaps this has been discussed before. Why is this packed? Is it to allow
unaligned access or to be sure that there is not implicitly added padding?
The Linux kernel does seem to need it.

> +
> +/*
> + * struct ffa_send_direct_data - Data structure hosting the data
> + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * @data0-4:	Data read/written from/to x3-x7 registers
> + *
> + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> + * or read from FFA_MSG_SEND_DIRECT_RESP
> + */
> +
> +/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
> +struct __packed ffa_send_direct_data {
> +	unsigned long data0; /* w3/x3 */
> +	unsigned long data1; /* w4/x4 */
> +	unsigned long data2; /* w5/x5 */
> +	unsigned long data3; /* w6/x6 */
> +	unsigned long data4; /* w7/x7 */
> +};

Why is this __packed? It seems unnecessary.

Cheers,
Jens

> +
> +/**
> + * struct ffa_bus_ops - The driver operations structure
> + * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
> + * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
> + * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
> + *
> + * The data structure providing all the operations supported by the driver.
> + * This structure is EFI runtime resident.
> + */
> +struct ffa_bus_ops {
> +	int (*partition_info_get)(const char *uuid_str,
> +				  u32 *parts_size, struct ffa_partition_info *buffer);
> +	int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg, bool is_smc64);
> +	int (*rxtx_unmap)(void);
> +};
> +
> +/**
> + * The device driver and the Uclass driver public functions
> + */
> +
> +/**
> + * ffa_bus_ops_get - driver operations getter
> + */
> +const struct ffa_bus_ops *ffa_bus_ops_get(void);
> +
> +/**
> + * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
> + */
> +int ffa_bus_discover(void);
> +
> +#endif
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 4b2c323452..fb59d4f356 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -4,6 +4,9 @@
>   *
>   * (C) Copyright 2012
>   * Pavel Herrmann <morpheus.ibis@gmail.com>
> + *
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #ifndef _DM_UCLASS_ID_H
> @@ -55,6 +58,7 @@ enum uclass_id {
>  	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
>  	UCLASS_ETH,		/* Ethernet device */
>  	UCLASS_ETH_PHY,		/* Ethernet PHY device */
> +	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
>  	UCLASS_FIRMWARE,	/* Firmware */
>  	UCLASS_FPGA,		/* FPGA device */
>  	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v7 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2022-11-08 13:47                                         ` Ilias Apalodimas
@ 2022-11-11 12:32                                           ` Abdellatif El Khlifi
  2022-11-11 12:36                                             ` Ilias Apalodimas
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-11 12:32 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, nd

On Tue, Nov 08, 2022 at 03:47:46PM +0200, Ilias Apalodimas wrote:
> Hi Abdellatif,
> 
> On Mon, Nov 07, 2022 at 07:20:47PM +0000, Abdellatif El Khlifi wrote:
> > convert UUID string to little endian binary data
> > 
> > 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>
> > 
> > ---
> > 
> > Changelog:
> > ===============
> > 
> > v7:
> > 
> > * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> > * make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
> >   by using same APIs
> > 
> > v4:
> > 
> > * rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
> >   a standalone commit (the current)
> > 
> > v3:
> > 
> > * introduce ffa_uuid_str_to_bin (provided by
> >   arm_ffa: introduce Arm FF-A low-level driver)
> > 
> > include/uuid.h |  8 ++++++++
> >  lib/uuid.c     | 46 ++++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 54 insertions(+)
> > 
> > diff --git a/include/uuid.h b/include/uuid.h
> > index 4a4883d3b5..293a8eb0a5 100644
> > --- a/include/uuid.h
> > +++ b/include/uuid.h
> > @@ -2,6 +2,8 @@
> >  /*
> >   * Copyright (C) 2014 Samsung Electronics
> >   * Przemyslaw Marczak <p.marczak@samsung.com>
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  #ifndef __UUID_H__
> >  #define __UUID_H__
> > @@ -44,4 +46,10 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
> >  const char *uuid_guid_get_str(const unsigned char *guid_bin);
> >  void gen_rand_uuid(unsigned char *uuid_bin);
> >  void gen_rand_uuid_str(char *uuid_str, int str_format);
> > +
> > +/**
> > + * uuid_str_to_le_bin - Converts a UUID string to little endian binary data
> > + */
> > +int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
> > +
> >  #endif
> > diff --git a/lib/uuid.c b/lib/uuid.c
> > index 465e1ac38f..cde5ae2bb7 100644
> > --- a/lib/uuid.c
> > +++ b/lib/uuid.c
> > @@ -1,6 +1,8 @@
> >  // SPDX-License-Identifier: GPL-2.0+
> >  /*
> >   * Copyright 2011 Calxeda, Inc.
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  
> >  #include <common.h>
> > @@ -346,6 +348,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
> >  	return 0;
> >  }
> >  
> > +/**
> > + * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
> > + * @uuid_str:	pointer to UUID string
> > + * @uuid_bin:	pointer to allocated array for little endian output [16B]
> > + *
> > + * UUID string is 36 characters (36 bytes):
> > + *
> > + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
> > + *
> > + * where x is a hexadecimal character. Fields are separated by '-'s.
> > + * When converting to a little endian binary UUID, the string fields are reversed.
> > + *
> > + * Return:
> > + *
> > + *    uuid_bin filled with little endian UUID data
> > + *    On success 0 is returned. Otherwise, failure code.
> > + */
> > +int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
> > +{
> > +	u16 tmp16;
> > +	u32 tmp32;
> > +	u64 tmp64;
> > +
> > +	if (!uuid_str_valid(uuid_str) || !uuid_bin)
> > +		return -EINVAL;
> > +
> > +	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
> > +	memcpy(uuid_bin, &tmp32, 4);
> > +
> > +	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
> > +	memcpy(uuid_bin + 4, &tmp16, 2);
> > +
> > +	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
> > +	memcpy(uuid_bin + 6, &tmp16, 2);
> > +
> > +	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
> > +	memcpy(uuid_bin + 8, &tmp16, 2);
> > +
> > +	tmp64 = cpu_to_le64(hextoul(uuid_str + 24, NULL));
> > +	memcpy(uuid_bin + 10, (char *)&tmp64, 6);
> 
> The cast isn't needed here 

A good catch , thanks for pointing out :) I'll fix that in v8.

> 
> > +
> > +	return 0;
> > +}
> > +
> >  /*
> >   * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
> >   *
> > -- 
> > 2.17.1
> > 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v7 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2022-11-11 12:32                                           ` Abdellatif El Khlifi
@ 2022-11-11 12:36                                             ` Ilias Apalodimas
  0 siblings, 0 replies; 478+ messages in thread
From: Ilias Apalodimas @ 2022-11-11 12:36 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: u-boot, nd

On Fri, 11 Nov 2022 at 14:32, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> On Tue, Nov 08, 2022 at 03:47:46PM +0200, Ilias Apalodimas wrote:
> > Hi Abdellatif,
> >
> > On Mon, Nov 07, 2022 at 07:20:47PM +0000, Abdellatif El Khlifi wrote:
> > > convert UUID string to little endian binary data
> > >
> > > 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>
> > >
> > > ---
> > >
> > > Changelog:
> > > ===============
> > >
> > > v7:
> > >
> > > * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> > > * make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
> > >   by using same APIs
> > >
> > > v4:
> > >
> > > * rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
> > >   a standalone commit (the current)
> > >
> > > v3:
> > >
> > > * introduce ffa_uuid_str_to_bin (provided by
> > >   arm_ffa: introduce Arm FF-A low-level driver)
> > >
> > > include/uuid.h |  8 ++++++++
> > >  lib/uuid.c     | 46 ++++++++++++++++++++++++++++++++++++++++++++++
> > >  2 files changed, 54 insertions(+)
> > >
> > > diff --git a/include/uuid.h b/include/uuid.h
> > > index 4a4883d3b5..293a8eb0a5 100644
> > > --- a/include/uuid.h
> > > +++ b/include/uuid.h
> > > @@ -2,6 +2,8 @@
> > >  /*
> > >   * Copyright (C) 2014 Samsung Electronics
> > >   * Przemyslaw Marczak <p.marczak@samsung.com>
> > > + * (C) Copyright 2022 ARM Limited
> > > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > >   */
> > >  #ifndef __UUID_H__
> > >  #define __UUID_H__
> > > @@ -44,4 +46,10 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
> > >  const char *uuid_guid_get_str(const unsigned char *guid_bin);
> > >  void gen_rand_uuid(unsigned char *uuid_bin);
> > >  void gen_rand_uuid_str(char *uuid_str, int str_format);
> > > +
> > > +/**
> > > + * uuid_str_to_le_bin - Converts a UUID string to little endian binary data
> > > + */
> > > +int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
> > > +
> > >  #endif
> > > diff --git a/lib/uuid.c b/lib/uuid.c
> > > index 465e1ac38f..cde5ae2bb7 100644
> > > --- a/lib/uuid.c
> > > +++ b/lib/uuid.c
> > > @@ -1,6 +1,8 @@
> > >  // SPDX-License-Identifier: GPL-2.0+
> > >  /*
> > >   * Copyright 2011 Calxeda, Inc.
> > > + * (C) Copyright 2022 ARM Limited
> > > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > >   */
> > >
> > >  #include <common.h>
> > > @@ -346,6 +348,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
> > >     return 0;
> > >  }
> > >
> > > +/**
> > > + * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
> > > + * @uuid_str:      pointer to UUID string
> > > + * @uuid_bin:      pointer to allocated array for little endian output [16B]
> > > + *
> > > + * UUID string is 36 characters (36 bytes):
> > > + *
> > > + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
> > > + *
> > > + * where x is a hexadecimal character. Fields are separated by '-'s.
> > > + * When converting to a little endian binary UUID, the string fields are reversed.
> > > + *
> > > + * Return:
> > > + *
> > > + *    uuid_bin filled with little endian UUID data
> > > + *    On success 0 is returned. Otherwise, failure code.
> > > + */
> > > +int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
> > > +{
> > > +   u16 tmp16;
> > > +   u32 tmp32;
> > > +   u64 tmp64;
> > > +
> > > +   if (!uuid_str_valid(uuid_str) || !uuid_bin)
> > > +           return -EINVAL;
> > > +
> > > +   tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
> > > +   memcpy(uuid_bin, &tmp32, 4);
> > > +
> > > +   tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
> > > +   memcpy(uuid_bin + 4, &tmp16, 2);
> > > +
> > > +   tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
> > > +   memcpy(uuid_bin + 6, &tmp16, 2);
> > > +
> > > +   tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
> > > +   memcpy(uuid_bin + 8, &tmp16, 2);
> > > +
> > > +   tmp64 = cpu_to_le64(hextoul(uuid_str + 24, NULL));
> > > +   memcpy(uuid_bin + 10, (char *)&tmp64, 6);
> >
> > The cast isn't needed here
>
> A good catch , thanks for pointing out :) I'll fix that in v8.

Sure, don't rush v8.  I'll go through the remaining either today or Monday

Thanks
/Ilias
>
> >
> > > +
> > > +   return 0;
> > > +}
> > > +
> > >  /*
> > >   * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
> > >   *
> > > --
> > > 2.17.1
> > >

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v7 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-09 11:51                                         ` Jens Wiklander
@ 2022-11-11 14:36                                           ` Abdellatif El Khlifi
  2022-11-15 10:32                                             ` Jens Wiklander
  2022-11-22 13:28                                           ` Abdellatif El Khlifi
  1 sibling, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-11 14:36 UTC (permalink / raw)
  To: Jens Wiklander; +Cc: u-boot, nd

On Wed, Nov 09, 2022 at 12:51:26PM +0100, Jens Wiklander wrote:
> On Mon, Nov 07, 2022 at 07:20:48PM +0000, Abdellatif El Khlifi wrote:
> > Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0
> > 
> > The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> > describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World leveraging TrustZone
> > technology.
> > 
> > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > querying the FF-A framework from the secure world.
> > 
> > The driver uses SMC32 calling convention which means using the first
> > 32-bit data of the Xn registers.
> > 
> > All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
> > which has 64-bit version supported.
> > 
> > Both 32-bit and 64-bit direct messaging are supported which allows both
> > 32-bit and 64-bit clients to use the FF-A bus.
> > 
> > In U-Boot FF-A design, FF-A is considered as a discoverable bus.
> > The Secure World is considered as one entity to communicate with
> > using the FF-A bus. FF-A communication is handled by one device and
> > one instance (the bus). This FF-A driver takes care of all the
> > interactions between Normal world and Secure World.
> > 
> > The driver exports its operations to be used by upper layers.
> > 
> > Exported operations:
> > 
> > - partition_info_get
> > - sync_send_receive
> > - rxtx_unmap
> > 
> > For more details please refer to the driver documentation [2].
> > 
> > [1]: https://developer.arm.com/documentation/den0077/latest/
> > [2]: doc/arch/arm64.ffa.rst
> > 
> > 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>
> > 
> > ---
> > 
> > Changelog:
> > ===============
> > 
> > v7:
> > 
> > * add support for 32-bit direct messaging
> > * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> > * improve the declaration of error handling mapping
> > * stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported
> > 
> > v6:
> > 
> > * drop use of EFI runtime support (We decided with Linaro to add this later)
> > * drop discovery from initcalls (discovery will be on demand by FF-A users)
> > * set the alignment of the RX/TX buffers to the larger translation granule size
> > * move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
> > * update the documentation and move it to doc/arch/arm64.ffa.rst
> > 
> > v4:
> > 
> > * add doc/README.ffa.drv
> > * moving the FF-A driver work to drivers/firmware/arm-ffa
> > * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
> >   #if defined by #if CONFIG_IS_ENABLED
> > * improving error handling by mapping the FF-A errors to standard errors
> >   and logs
> > * replacing panics with an error log and returning an error code
> > * improving features discovery in FFA_FEATURES by introducing
> >   rxtx_min_pages private data field
> > * add ffa_remove and ffa_unbind functions
> > * improve how the driver behaves when bus discovery is done more than
> >   once
> > 
> > v3:
> > 
> > * align the interfaces of the U-Boot FF-A driver with those in the linux
> >   FF-A driver
> > * remove the FF-A helper layer
> > * make the U-Boot FF-A driver independent from EFI
> > * provide an optional config that enables copying the driver data to EFI
> >   runtime section at ExitBootServices service
> > * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
> > 
> > v2:
> > 
> > * make FF-A bus discoverable using device_{bind, probe} APIs
> > * remove device tree support
> > 
> > v1:
> > 
> > * introduce FF-A bus driver with device tree support
> > 
> > MAINTAINERS                               |    7 +
> >  doc/arch/arm64.ffa.rst                    |  218 ++++
> >  doc/arch/index.rst                        |    1 +
> >  drivers/Kconfig                           |    2 +
> >  drivers/Makefile                          |    1 +
> >  drivers/firmware/arm-ffa/Kconfig          |   30 +
> >  drivers/firmware/arm-ffa/Makefile         |    6 +
> >  drivers/firmware/arm-ffa/arm-ffa-uclass.c |   16 +
> >  drivers/firmware/arm-ffa/arm_ffa_prv.h    |  205 ++++
> >  drivers/firmware/arm-ffa/core.c           | 1310 +++++++++++++++++++++
> >  include/arm_ffa.h                         |   93 ++
> >  include/dm/uclass-id.h                    |    4 +
> >  12 files changed, 1893 insertions(+)
> >  create mode 100644 doc/arch/arm64.ffa.rst
> >  create mode 100644 drivers/firmware/arm-ffa/Kconfig
> >  create mode 100644 drivers/firmware/arm-ffa/Makefile
> >  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
> >  create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
> >  create mode 100644 drivers/firmware/arm-ffa/core.c
> >  create mode 100644 include/arm_ffa.h
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 1cf99c1393..450b5725ce 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -263,6 +263,13 @@ F:	drivers/net/cortina_ni.h
> >  F:	drivers/net/phy/ca_phy.c
> >  F:	configs/cortina_presidio-asic-pnand_defconfig
> >  
> > +ARM FF-A
> > +M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > +S:	Maintained
> > +F:	doc/arch/arm64.ffa.rst
> > +F:	drivers/firmware/arm-ffa/
> > +F:	include/arm_ffa.h
> > +
> >  ARM FREESCALE IMX
> >  M:	Stefano Babic <sbabic@denx.de>
> >  M:	Fabio Estevam <festevam@gmail.com>
> > diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> > new file mode 100644
> > index 0000000000..dfcec82e45
> > --- /dev/null
> > +++ b/doc/arch/arm64.ffa.rst
> > @@ -0,0 +1,218 @@
> > +.. SPDX-License-Identifier: GPL-2.0+
> > +
> > +Arm FF-A Driver
> > +===============
> > +
> > +Summary
> > +-------
> > +
> > +FF-A stands for Firmware Framework for Arm A-profile processors.
> > +
> > +FF-A specifies interfaces that enable a pair of software sandboxes to
> > +communicate with each other. A sandbox aka partition could
> > +be a VM in the Normal or Secure world, an application in S-EL0, or a
> > +Trusted OS in S-EL1.
> > +
> > +This FF-A driver implements the interfaces to communicate with partitions in
> > +the Secure world aka Secure partitions (SPs).
> > +
> > +The driver specifically focuses on communicating with SPs that isolate portions
> > +of EFI runtime services that must run in a protected environment which is
> > +inaccessible by the Host OS or Hypervisor. Examples of such services are
> > +set/get variables.
> > +
> > +FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> > +
> > +- Discover the presence of SPs of interest
> > +- Access an SP's service through communication protocols
> > +  e.g. EFI MM communication protocol
> > +
> > +At this stage of development the FF-A driver supports EFI boot time only.
> > +
> > +Runtime support will be added in future developments.
> > +
> > +FF-A and SMC specifications
> > +-------------------------------------------
> > +
> > +The current implementation of the driver relies on FF-A specification v1.0
> > +and uses SMC32 calling convention which means using the first 32-bit data of the
> > +Xn registers.
> > +
> > +At this stage we only need the FF-A v1.0 features.
> > +
> > +The driver has been tested with OP-TEE which supports SMC32 calling convention.
> > +
> > +For more details please refer to the FF-A v1.0 spec:
> > +https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=
> > +
> > +Hypervisors are supported if they are configured to trap SMC calls.
> > +
> > +The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
> > +
> > +For more details please refer to the SMC Calling Convention v1.2 spec:
> > +https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
> > +
> > +Supported hardware
> > +--------------------------------
> > +
> > +Aarch64 plaforms
> > +
> > +Configuration
> > +----------------------
> > +
> > +CONFIG_ARM_FFA_TRANSPORT
> > +    Enables the FF-A bus driver. Turn this on if you want to use FF-A
> > +    communication.
> > +
> > +CONFIG_SANDBOX_FFA
> > +    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
> > +    Sandbox and provides functional tests for FF-A.
> > +
> > +FF-A ABIs under the hood
> > +---------------------------------------
> > +
> > +Invoking an FF-A ABI involves providing to the secure world/hypervisor the
> > +expected arguments from the ABI.
> > +
> > +The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction
> > +is executed.
> > +
> > +At the secure side level or hypervisor the ABI is handled at a higher exception
> > +level and the arguments are read and processed.
> > +
> > +The response is put back through x0 to x7 registers and control is given back
> > +to the U-Boot FF-A driver (non-secure world).
> > +
> > +The driver reads the response and processes it accordingly.
> > +
> > +This methodology applies to all the FF-A ABIs in the driver.
> > +
> > +FF-A bus discovery in U-Boot
> > +-------------------------------------------
> > +
> > +When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is discovered on
> > +demand by the clients (users).
> > +
> > +Clients can discover the FF-A bus using ffa_bus_discover() API which triggers the
> > +discovery process.
> > +
> > +ffa_bus_discover() creates, binds and probes the arm_ffa device using
> > +device_{bind, probe} APIs.
> > +
> > +The discovery process consists in communicating with secure world (or hypervisor)
> > +and querying specific data.
> > +
> > +The discovery process takes place during the arm_ffa device probing which is
> > +handled by ffa_probe().
> > +
> > +The FF-A bus discovery is successful and the bus is ready for use when these
> > +operations succeed:
> > +
> > +- querying the FF-A framework version
> > +- querying from secure world the U-Boot endpoint ID
> > +- querying from secure world the RX/TX mapping  features
> > +- mapping the RX/TX buffers
> > +- querying from secure world all the partitions information
> > +
> > +Discovery failure results in a probing failure and the arm_ffa device is
> > +destroyed.
> > +
> > +Requirements for clients
> > +-------------------------------------
> > +
> > +When using the FF-A bus with EFI, clients must:
> > +
> > +- Query SPs in EFI boot time mode using the service UUID.
> > +- Unmap RX/TX buffers before EFI runtime mode starts.
> > +
> > +The RX/TX buffers are only available at EFI boot time. Querying partitions is
> > +done at boot time and data is cached for future use.
> > +
> > +RX/TX buffers should be unmapped by the user before EFI runtime mode
> > +starts. The driver provides a bus operation for that: rxtx_unmap()
> > +
> > +If  RX/TX buffers created by U-Boot are not unmapped and by
> > +consequence becoming available at EFI runtime, secure world will get confused
> > +about RX/TX buffers ownership (U-Boot vs kernel).
> > +
> > +When invoking FF-A direct messaging, clients should specify which ABI protocol
> > +they want to use (32-bit vs 64-bit). Selecting the protocol means using
> > +the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> > +The calling convention stays the same: SMC32.
> > +
> > +The bus driver layer
> > +------------------------------
> > +
> > +The driver comes on top of the SMCCC layer and is implemented in
> > +drivers/firmware/arm-ffa/core.c
> > +
> > +The driver provides the following features:
> > +
> > +- Support for the 32-bit version of the following ABIs:
> > +
> > +FFA_VERSION
> > +FFA_ID_GET
> > +FFA_FEATURES
> > +FFA_PARTITION_INFO_GET
> > +FFA_RXTX_UNMAP
> > +FFA_RX_RELEASE
> > +FFA_RUN
> > +FFA_ERROR
> > +FFA_SUCCESS
> > +FFA_INTERRUPT
> > +FFA_MSG_SEND_DIRECT_REQ
> > +FFA_MSG_SEND_DIRECT_RESP
> > +
> > +- Support for the 64-bit version of the following ABIs:
> > +
> > +FFA_RXTX_MAP
> > +FFA_MSG_SEND_DIRECT_REQ
> > +FFA_MSG_SEND_DIRECT_RESP
> > +
> > +- Processing the received data from the secure world/hypervisor and caching it
> > +
> > +- Hiding from upper layers the FF-A protocol and registers details. Upper
> > +  layers focus on exchanged data, the driver takes care of how to transport
> > +  that to the secure world/hypervisor using FF-A
> > +
> > +- The driver provides callbacks to be used by clients to access the FF-A bus:
> > +
> > +partition_info_get
> > +sync_send_receive
> > +rxtx_unmap
> > +
> > +- FF-A bus discovery makes sure FF-A framework is responsive and compatible
> > +  with the driver
> > +
> > +- FF-A bus can be compiled and used without EFI
> > +
> > +Using armffa command
> > +-----------------------------------
> > +
> > +armffa is an implementation defined command showcasing how to use the FF-A driver and how to invoke
> > +its operations.
> > +
> > +This provides a guidance to the client developers on how to call the FF-A bus
> > +interfaces.
> > +
> > +Usage:
> > +
> > +armffa <sub-command> <arguments>
> > +
> > +sub-commands:
> > +
> > +        getpart <partition UUID>
> > +
> > +            lists the partition(s) info
> > +
> > +        ping <partition ID>
> > +
> > +            sends a data pattern to the specified partition
> > +
> > +        devlist
> > +
> > +            displays the arm_ffa device info
> > +
> > +Contributors
> > +------------
> > +   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > diff --git a/doc/arch/index.rst b/doc/arch/index.rst
> > index 792d9182c3..8d1ab0ad4e 100644
> > --- a/doc/arch/index.rst
> > +++ b/doc/arch/index.rst
> > @@ -8,6 +8,7 @@ Architecture-specific doc
> >  
> >     arc
> >     arm64
> > +   arm64.ffa
> >     m68k
> >     mips
> >     nios2
> > diff --git a/drivers/Kconfig b/drivers/Kconfig
> > index 8b6fead351..b06b1ae481 100644
> > --- a/drivers/Kconfig
> > +++ b/drivers/Kconfig
> > @@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
> >  
> >  source "drivers/adc/Kconfig"
> >  
> > +source "drivers/firmware/arm-ffa/Kconfig"
> > +
> >  source "drivers/ata/Kconfig"
> >  
> >  source "drivers/axi/Kconfig"
> > diff --git a/drivers/Makefile b/drivers/Makefile
> > index a1700c819d..b86c1d2a42 100644
> > --- a/drivers/Makefile
> > +++ b/drivers/Makefile
> > @@ -111,6 +111,7 @@ obj-y += iommu/
> >  obj-y += smem/
> >  obj-y += thermal/
> >  obj-$(CONFIG_TEE) += tee/
> > +obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
> >  obj-y += axi/
> >  obj-y += ufs/
> >  obj-$(CONFIG_W1) += w1/
> > diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> > new file mode 100644
> > index 0000000000..e4914b9bc7
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/Kconfig
> > @@ -0,0 +1,30 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +config ARM_FFA_TRANSPORT
> > +	bool "Enable Arm Firmware Framework for Armv8-A driver"
> > +	depends on DM && ARM64
> > +	select ARM_SMCCC
> > +	select LIB_UUID
> > +	select DEVRES
> > +	help
> > +	  The Firmware Framework for Arm A-profile processors (FF-A)
> > +	  describes interfaces (ABIs) that standardize communication
> > +	  between the Secure World and Normal World leveraging TrustZone
> > +	  technology.
> > +
> > +	  This driver is based on FF-A specification v1.0 and uses SMC32
> > +	  calling convention.
> > +
> > +	  FF-A specification:
> > +
> > +	  https://developer.arm.com/documentation/den0077/a/?lang=en
> > +
> > +	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
> > +	  The Secure World is considered as one entity to communicate with
> > +	  using the FF-A bus.
> > +	  FF-A communication is handled by one device and one instance (the bus).
> > +	  This FF-A driver takes care of all the interactions between Normal world
> > +	  and Secure World.
> > +
> > +	  For more details about the FF-A driver, please refer to doc/arch/arm64.ffa.rst
> > +
> > diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
> > new file mode 100644
> > index 0000000000..043a8915be
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/Makefile
> > @@ -0,0 +1,6 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +#
> > +# (C) Copyright 2022
> > +# Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com.
> > +
> > +obj-y += arm-ffa-uclass.o core.o
> > diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> > new file mode 100644
> > index 0000000000..7d9695d289
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> > @@ -0,0 +1,16 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <asm/global_data.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +UCLASS_DRIVER(ffa) = {
> > +	.name		= "ffa",
> > +	.id		= UCLASS_FFA,
> > +};
> > diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> > new file mode 100644
> > index 0000000000..ad7430ada9
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> > @@ -0,0 +1,205 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_PRV_H
> > +#define __ARM_FFA_PRV_H
> > +
> > +#include <arm_ffa.h>
> > +#include <linux/bitfield.h>
> > +#include <linux/bitops.h>
> > +#include <linux/arm-smccc.h>
> > +
> > +/*
> > + * This header is private. It is exclusively used by the FF-A driver
> > + */
> > +
> > +/* FF-A core driver name */
> > +#define FFA_DRV_NAME "arm_ffa"
> > +
> > +/* FF-A driver version definitions */
> > +
> > +#define MAJOR_VERSION_MASK		GENMASK(30, 16)
> > +#define MINOR_VERSION_MASK		GENMASK(15, 0)
> > +#define GET_FFA_MAJOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> > +#define GET_FFA_MINOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> > +#define PACK_VERSION_INFO(major, minor)			\
> > +	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
> > +	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> > +
> > +#define FFA_MAJOR_VERSION		(1)
> > +#define FFA_MINOR_VERSION		(0)
> > +#define FFA_VERSION_1_0		\
> > +			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> > +
> > +/* Endpoint ID mask (u-boot endpoint ID) */
> > +
> > +#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define GET_SELF_ENDPOINT_ID(x)		\
> > +			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> > +
> > +#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
> > +#define PREP_SELF_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> > +
> > +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> > +
> > +#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define PREP_PART_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> > +
> > +/*
> > + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> > + */
> > +
> > +#define FFA_SMC(calling_convention, func_num)				\
> > +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
> > +			   ARM_SMCCC_OWNER_STANDARD, (func_num))
> > +
> > +#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> > +#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
> > +
> > +enum ffa_abis {
> > +	FFA_ERROR					= 0x60,
> > +	FFA_SUCCESS					= 0x61,
> > +	FFA_INTERRUPT				= 0x62,
> > +	FFA_VERSION					= 0x63,
> > +	FFA_FEATURES				= 0x64,
> > +	FFA_RX_RELEASE				= 0x65,
> > +	FFA_RXTX_MAP				= 0x66,
> > +	FFA_RXTX_UNMAP			= 0x67,
> > +	FFA_PARTITION_INFO_GET		= 0x68,
> > +	FFA_ID_GET					= 0x69,
> > +	FFA_RUN						= 0x6D,
> > +	FFA_MSG_SEND_DIRECT_REQ	= 0x6F,
> > +	FFA_MSG_SEND_DIRECT_RESP	= 0x70,
> 
> Strange indentation above.
> 
> > +
> > +	/* to be updated when adding new FFA IDs */
> > +	FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
> > +	FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
> > +};
> > +
> > +enum ffa_abi_errcode {
> > +	NOT_SUPPORTED = 1,
> > +	INVALID_PARAMETERS,
> > +	NO_MEMORY,
> > +	BUSY,
> > +	INTERRUPTED,
> > +	DENIED,
> > +	RETRY,
> > +	ABORTED,
> > +	MAX_NUMBER_FFA_ERR
> > +};
> > +
> > +/* container structure and helper macros to map between an FF-A error and relevant error log */
> > +struct ffa_abi_errmap {
> > +	char *err_str[MAX_NUMBER_FFA_ERR];
> > +};
> > +
> > +#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
> > + *
> > + */
> > +struct ffa_partition_uuid {
> > +	u32 a1; /* w1 */
> > +	u32 a2; /* w2 */
> > +	u32 a3; /* w3 */
> > +	u32 a4; /* w4 */
> > +};
> > +
> > +/**
> > + * enum ffa_rxtx_buf_sizes - minimum sizes supported
> > + * for the RX/TX buffers
> > + */
> > +enum ffa_rxtx_buf_sizes {
> > +	RXTX_4K,
> > +	RXTX_64K,
> > +	RXTX_16K
> > +};
> > +
> > +/**
> > + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> > + * @rxbuf:	virtual address of the RX buffer
> > + * @txbuf:	virtual address of the TX buffer
> > + * @rxtx_min_pages:	RX/TX buffers minimum size in pages
> > + *
> > + * Data structure hosting the virtual addresses of the mapped RX/TX buffers
> > + * These addresses are used by the FF-A functions that use the RX/TX buffers
> > + */
> > +struct ffa_rxtxpair {
> > +	u64 rxbuf; /* virtual address */
> > +	u64 txbuf; /* virtual address */
> > +	size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
> > +};
> > +
> > +/**
> > + * struct ffa_partition_desc - the secure partition descriptor
> > + * @info:	partition information
> > + * @sp_uuid:	the secure partition UUID
> > + *
> > + * Each partition has its descriptor containing the partitions information and the UUID
> > + */
> > +struct ffa_partition_desc {
> > +	struct ffa_partition_info info;
> > +	struct ffa_partition_uuid sp_uuid;
> > +};
> > +
> > +/**
> > + * struct ffa_partitions - descriptors for all secure partitions
> > + * @count:	The number of partitions descriptors
> > + * @descs	The partitions descriptors table
> > + *
> > + * This data structure contains the partitions descriptors table
> > + */
> > +struct ffa_partitions {
> > +	u32 count;
> > +	struct ffa_partition_desc *descs; /* virtual address */
> > +};
> > +
> > +/**
> > + * struct ffa_prvdata - the driver private data structure
> > + *
> > + * @dev:	The arm_ffa device under u-boot driver model
> > + * @ffa_ops:	The driver operations structure
> > + * @fwk_version:	FF-A framework version
> > + * @id:	u-boot endpoint ID
> > + * @partitions:	The partitions descriptors structure
> > + * @pair:	The RX/TX buffers pair
> > + * @invoke_ffa_fn:	The function executing the FF-A function
> > + *
> > + * The driver data structure hosting all resident data.
> > + */
> > +struct ffa_prvdata {
> > +	struct udevice *dev;
> > +	struct ffa_bus_ops ffa_ops;
> > +	u32 fwk_version;
> > +	u16 id;
> > +	struct ffa_partitions partitions;
> > +	struct ffa_rxtxpair pair;
> > +	invoke_ffa_fn_t invoke_ffa_fn;
> > +};
> > +
> > +/**
> > + * ffa_device_get - create, bind and probe the arm_ffa device
> > + */
> > +int ffa_device_get(void);
> > +
> > +/**
> > + * ffa_bus_prvdata_get - bus driver private data getter
> > + */
> > +struct ffa_prvdata **ffa_bus_prvdata_get(void);
> > +
> > +#endif
> > diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
> > new file mode 100644
> > index 0000000000..b955e5187b
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/core.c
> > @@ -0,0 +1,1310 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include "arm_ffa_prv.h"
> > +#include <asm/global_data.h>
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <dm/device-internal.h>
> > +#include <dm/devres.h>
> > +#include <dm/root.h>
> > +#include <linux/errno.h>
> > +#include <linux/sizes.h>
> > +#include <log.h>
> > +#include <malloc.h>
> > +#include <string.h>
> > +#include <uuid.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/**
> > + * The device private data structure containing all the
> > + * data read from secure world
> > + */
> > +struct ffa_prvdata *ffa_priv_data;
> > +
> > +/* Error mapping declarations */
> > +
> > +int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
> > +	[NOT_SUPPORTED] = -EOPNOTSUPP,
> > +	[INVALID_PARAMETERS] = -EINVAL,
> > +	[NO_MEMORY] = -ENOMEM,
> > +	[BUSY] = -EBUSY,
> > +	[INTERRUPTED] = -EINTR,
> > +	[DENIED] = -EACCES,
> > +	[RETRY] = -EAGAIN,
> > +	[ABORTED] = -ECANCELED,
> > +};
> > +
> > +struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
> > +		{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
> > +		{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
> > +		{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
> > +		{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +			[INVALID_PARAMETERS] =
> > +			"INVALID_PARAMETERS: Unrecognized UUID",
> > +			[NO_MEMORY] =
> > +			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
> > +			[BUSY] =
> > +			"BUSY: RX buffer of the caller is not free",
> > +			[DENIED] =
> > +			"DENIED: Callee is not in a state to handle this request",
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
> > +			{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
> > +			[INVALID_PARAMETERS] =
> > +			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
> > +			{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
> > +			[DENIED] =
> > +			"DENIED: Caller did not have ownership of the RX buffer",
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
> > +			{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +			[INVALID_PARAMETERS] =
> > +			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
> > +			[NO_MEMORY] =
> > +			"NO_MEMORY: Not enough memory",
> > +			[DENIED] =
> > +			"DENIED: Buffer pair already registered",
> > +		},
> > +	},
> > +};
> 
> Indentation above looks strange and inconsistent in some places. This
> entire approach is in my opinion a bit complicated, no big deal, if no
> one else complains I suppose it's OK.
> 
> > +
> > +/**
> > + * ffa_to_std_errno - convert FF-A error code to standard error code
> > + * @ffa_errno:	Error code returned by the FF-A ABI
> > + *
> > + * This function maps the given FF-A error code as specified
> > + * by the spec to a u-boot standard error code.
> > + *
> > + * Return:
> > + *
> > + * The standard error code on success. . Otherwise, failure
> > + */
> > +int ffa_to_std_errno(int ffa_errno)
> > +{
> > +	int err_idx = -ffa_errno;
> > +
> > +	/* map the FF-A error code to the standard u-boot error code */
> > +	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
> > +		return ffa_to_std_errmap[err_idx];
> > +	return -EINVAL;
> > +}
> > +
> > +/**
> > + * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
> > + * @ffa_id:	FF-A ABI ID
> > + * @ffa_errno:	Error code returned by the FF-A ABI
> > + *
> > + * This function maps the FF-A error code to the error log relevant to the
> > + * selected FF-A ABI. Then the error log is printed.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. . Otherwise, failure
> > + */
> > +int ffa_print_error_log(u32 ffa_id, int ffa_errno)
> > +{
> > +	int err_idx = -ffa_errno, abi_idx = 0;
> > +
> > +	/* map the FF-A error code to the corresponding error log */
> > +
> > +	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
> > +		return -EINVAL;
> > +
> > +	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
> > +		return -EINVAL;
> > +
> > +	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
> > +	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
> > +		return -EINVAL;
> > +
> > +	if (!err_msg_map[abi_idx].err_str[err_idx])
> > +		return -EINVAL;
> > +
> > +	ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Driver core functions
> > + */
> > +
> > +/**
> > + * ffa_remove_device - removes the arm_ffa device
> > + * @dev:	the device to be removed
> > + *
> > + * This function makes sure the arm_ffa device is removed
> > + * No need to free the kmalloced data when the device is destroyed.
> > + * It's automatically done by devm management by
> > + * device_remove() -> device_free() -> devres_release_probe().
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_remove_device(struct udevice *dev)
> > +{
> > +	int ret;
> > +
> > +	if (!dev) {
> > +		ffa_err("no udevice found");
> > +		return -ENODEV;
> > +	}
> > +
> > +	ret = device_remove(dev, DM_REMOVE_NORMAL);
> > +	if (ret) {
> > +		ffa_err("unable to remove. err:%d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	ffa_info("device removed and freed");
> > +
> > +	ret = device_unbind(dev);
> > +	if (ret) {
> > +		ffa_err("unable to unbind. err:%d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	ffa_info("device unbound");
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_device_get - create, bind and probe the arm_ffa device
> > + *
> > + * This function makes sure the arm_ffa device is
> > + * created, bound to this driver, probed and ready to use.
> > + * Arm FF-A transport is implemented through a single u-boot
> > + * device managing the FF-A bus (arm_ffa).
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_device_get(void)
> > +{
> > +	int ret;
> > +	struct udevice *dev = NULL;
> > +
> > +	ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > +			  &dev);
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* The FF-A bus discovery succeeds when probing is successful */
> > +	ret = device_probe(dev);
> > +	if (ret) {
> > +		ffa_err("arm_ffa device probing failed");
> > +		ffa_remove_device(dev);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_get_version - FFA_VERSION handler function
> > + *
> > + * This function implements FFA_VERSION FF-A function
> > + * to get from the secure world the FF-A framework version
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_version(void)
> > +{
> > +	u16 major, minor;
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
> > +			}, &res);
> > +
> > +	ffa_errno = res.a0;
> > +	if (ffa_errno < 0) {
> > +		ffa_print_error_log(FFA_VERSION, ffa_errno);
> > +		return ffa_to_std_errno(ffa_errno);
> > +	}
> > +
> > +	major = GET_FFA_MAJOR_VERSION(res.a0);
> > +	minor = GET_FFA_MINOR_VERSION(res.a0);
> > +
> > +	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> > +		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
> > +		ffa_info("Versions are compatible ");
> > +
> > +		ffa_priv_data->fwk_version = res.a0;
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
> > +		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +	return -EPROTONOSUPPORT;
> > +}
> > +
> > +/**
> > + * ffa_get_endpoint_id - FFA_ID_GET handler function
> > + *
> > + * This function implements FFA_ID_GET FF-A function
> > + * to get from the secure world u-boot endpoint ID
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_endpoint_id(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_ID_GET),
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
> > +		ffa_info("endpoint ID is %u", ffa_priv_data->id);
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +
> > +	ffa_print_error_log(FFA_ID_GET, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
> > + * @prop_field: properties field obtained from FFA_FEATURES ABI
> > + *
> > + * This function sets the minimum number of pages
> > + *  in each of the RX/TX buffers in the private data structure
> > + *
> > + * Return:
> > + *
> > + * buf_4k_pages points to the returned number of pages
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
> > +{
> > +	if (!ffa_priv_data)
> > +		return -EINVAL;
> > +
> > +	switch (prop_field) {
> > +	case RXTX_4K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 1;
> > +		break;
> > +	case RXTX_16K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 4;
> > +		break;
> > +	case RXTX_64K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 16;
> > +		break;
> > +	default:
> > +		ffa_err("RX/TX buffer size not supported");
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
> > + *
> > + * This function implements FFA_FEATURES FF-A function
> > + * to retrieve the FFA_RXTX_MAP features
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_rxtx_map_features(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_FEATURES),
> > +			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> > +		return ffa_set_rxtx_buffers_pages_cnt(res.a2);
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_FEATURES, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> > + *
> > + * This  function  frees the RX/TX buffers
> > + *
> > + */
> > +static void ffa_free_rxtx_buffers(void)
> > +{
> > +	ffa_info("Freeing RX/TX buffers");
> > +
> > +	if (ffa_priv_data->pair.rxbuf) {
> > +		free((void *)ffa_priv_data->pair.rxbuf);
> > +		ffa_priv_data->pair.rxbuf = 0;
> > +	}
> > +
> > +	if (ffa_priv_data->pair.txbuf) {
> > +		free((void *)ffa_priv_data->pair.txbuf);
> > +		ffa_priv_data->pair.txbuf = 0;
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
> > + *
> > + * This function is used by ffa_map_rxtx_buffers to allocate
> > + * the RX/TX buffers before mapping them. The allocated memory is physically
> > + * contiguous since memalign ends up calling malloc which allocates
> > + * contiguous memory in u-boot.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_alloc_rxtx_buffers(void)
> > +{
> > +	u64 bytes;
> > +
> > +	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
> > +		 ffa_priv_data->pair.rxtx_min_pages);
> > +
> > +	bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> > +
> > +	/*
> > +	 * The alignment of the RX and TX buffers must be equal
> > +	 * to the larger translation granule size
> > +	 */
> > +
> > +	ffa_priv_data->pair.rxbuf = (u64)memalign(bytes, bytes);
> > +	if (!ffa_priv_data->pair.rxbuf) {
> > +		ffa_err("failure to allocate RX buffer");
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
> > +
> > +	ffa_priv_data->pair.txbuf = (u64)memalign(bytes, bytes);
> > +	if (!ffa_priv_data->pair.txbuf) {
> > +		free((void *)ffa_priv_data->pair.rxbuf);
> > +		ffa_priv_data->pair.rxbuf = 0;
> > +		ffa_err("failure to allocate the TX buffer");
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
> > +
> > +	/*
> > +	 * make sure the buffers are cleared before use
> > +	 */
> > +	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
> > +	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> > + *
> > + * This function implements FFA_RXTX_MAP FF-A function
> > + * to map the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_map_rxtx_buffers(void)
> > +{
> > +	int ret;
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ret = ffa_alloc_rxtx_buffers();
> > +	if (ret)
> > +		return ret;
> > +
> > +	/*
> > +	 * we need to pass the physical addresses of the RX/TX buffers
> > +	 * in u-boot physical/virtual mapping is 1:1
> > +	 * no need to convert from virtual to physical
> > +	 */
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
> > +			.a1 = ffa_priv_data->pair.txbuf,
> > +			.a2 = ffa_priv_data->pair.rxbuf,
> > +			.a3 = ffa_priv_data->pair.rxtx_min_pages,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_info("RX/TX buffers mapped");
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
> > +
> > +	ffa_free_rxtx_buffers();
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
> > + *
> > + * This function implements FFA_RXTX_UNMAP FF-A function
> > + * to unmap the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_unmap_rxtx_buffers(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
> > +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id),
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_free_rxtx_buffers();
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
> > + *
> > + * This function invokes FFA_RX_RELEASE FF-A function
> > + * to release the ownership of the RX buffer
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_release_rx_buffer(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> > +		return 0;
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_uuid_are_identical - checks whether two given UUIDs are identical
> > + * @uuid1: first UUID
> > + * @uuid2: second UUID
> > + *
> > + * This function is used by ffa_read_partitions_info to search
> > + * for a UUID in the partitions descriptors table
> > + *
> > + * Return:
> > + *
> > + * 1 when UUIDs match. Otherwise, 0
> > + */
> > +bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
> > +			    const struct ffa_partition_uuid *uuid2)
> > +{
> > +	if (!uuid1 || !uuid2)
> > +		return 0;
> > +
> > +	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
> > +}
> > +
> > +/**
> > + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> > + *							and saves it in the private structure
> > + * @count: The number of partitions queried
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + *
> > + * This function reads the partitions information
> > + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> > + * data structure.
> > + *
> > + * Return:
> > + *
> > + * The private data structure is updated with the partition(s) information
> > + * 0 is returned on success. Otherwise, failure
> > + */
> > +static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
> > +{
> > +	if (!count) {
> > +		ffa_err("no partition detected");
> > +		return -ENODATA;
> > +	}
> > +
> > +	ffa_info("Reading partitions data from the RX buffer");
> > +
> > +	if (!part_uuid) {
> > +		/*
> > +		 * querying information of all partitions
> > +		 */
> > +		u64 buf_bytes;
> > +		u64 data_bytes;
> > +		u32 desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +
> > +		data_bytes = count * sizeof(struct ffa_partition_desc);
> > +
> > +		buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> > +
> > +		if (data_bytes > buf_bytes) {
> > +			ffa_err("partitions data size exceeds the RX buffer size:");
> > +			ffa_err("    sizes in bytes: data %llu , RX buffer %llu ",
> > +				data_bytes,
> > +				buf_bytes);
> > +
> > +			return -ENOMEM;
> > +		}
> > +
> > +		ffa_priv_data->partitions.descs = devm_kmalloc(ffa_priv_data->dev, data_bytes,
> > +							       __GFP_ZERO);
> > +		if (!ffa_priv_data->partitions.descs) {
> > +			ffa_err("cannot  allocate partitions data buffer");
> > +			return -ENOMEM;
> > +		}
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> > +
> > +		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
> > +			ffa_priv_data->partitions.descs[desc_idx].info =
> > +				parts_info[desc_idx];
> > +
> > +			ffa_info("Partition ID %x : info cached",
> > +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> > +		}
> > +
> > +		ffa_priv_data->partitions.count = count;
> > +
> > +		ffa_info("%d partition(s) found and cached", count);
> > +
> > +	} else {
> > +		u32 rx_desc_idx, cached_desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +		u8 desc_found;
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> > +
> > +		/*
> > +		 * search for the SP IDs read from the RX buffer
> > +		 * in the already cached SPs.
> > +		 * Update the UUID when ID found.
> > +		 */
> > +		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
> > +			desc_found = 0;
> > +
> > +			/*
> > +			 * search the current ID in the cached partitions
> > +			 */
> > +			for (cached_desc_idx = 0;
> > +			     cached_desc_idx < ffa_priv_data->partitions.count;
> > +			     cached_desc_idx++) {
> > +				/*
> > +				 * save the UUID
> > +				 */
> > +				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
> > +				    parts_info[rx_desc_idx].id) {
> > +					ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
> > +						*part_uuid;
> > +
> > +					desc_found = 1;
> > +					break;
> > +				}
> > +			}
> > +
> > +			if (!desc_found)
> > +				return -ENODATA;
> > +		}
> > +	}
> > +
> > +	return  0;
> > +}
> > +
> > +/**
> > + * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
> > + *
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + * @pcount: Pointer to the number of partitions variable filled when querying
> > + *
> > + * This function executes the FFA_PARTITION_INFO_GET
> > + * to query the partitions data. Then, it calls ffa_read_partitions_info
> > + * to save the data in the private data structure.
> > + *
> > + * After reading the data the RX buffer is released using ffa_release_rx_buffer
> > + *
> > + * Return:
> > + *
> > + * When part_uuid is NULL, all partitions data are retrieved from secure world
> > + * When part_uuid is non NULL, data for partitions matching the given UUID are
> > + * retrieved and the number of partitions is returned
> > + * 0 is returned on success. Otherwise, failure
> > + */
> > +static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
> > +				     u32 *pcount)
> > +{
> > +	struct ffa_partition_uuid query_uuid = {0};
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	/*
> > +	 * If a UUID is specified. Information for one or more
> > +	 * partitions in the system is queried. Otherwise, information
> > +	 * for all installed partitions is queried
> > +	 */
> > +
> > +	if (part_uuid) {
> > +		if (!pcount)
> > +			return -EINVAL;
> > +
> > +		query_uuid = *part_uuid;
> > +	} else if (pcount) {
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
> > +			.a1 = query_uuid.a1,
> > +			.a2 = query_uuid.a2,
> > +			.a3 = query_uuid.a3,
> > +			.a4 = query_uuid.a4,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		int ret;
> > +
> > +		/*
> > +		 * res.a2 contains the count of partition information descriptors
> > +		 * populated in the RX buffer
> > +		 */
> > +		if (res.a2) {
> > +			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
> > +			if (ret) {
> > +				ffa_err("failed to read partition(s) data , error (%d)", ret);
> > +				ffa_release_rx_buffer();
> > +				return -EINVAL;
> > +			}
> > +		}
> > +
> > +		/*
> > +		 * return the SP count (when querying using a UUID)
> > +		 */
> > +		if (pcount)
> > +			*pcount = (u32)res.a2;
> > +
> > +		/*
> > +		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
> > +		 * is assigned to the consumer (u-boot). So, we need to give
> > +		 * the ownership back to the SPM or hypervisor
> > +		 */
> > +		ret = ffa_release_rx_buffer();
> > +
> > +		return ret;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
> > + *
> > + * The passed arguments:
> > + * Mode 1: When getting from the driver the number of
> > + *	secure partitions:
> > + *	@uuid_str: pointer to the UUID string
> > + *	@parts_size: pointer to the variable that contains the number of partitions
> > + *			 The variable will be set by the driver
> > + *	@buffer: NULL
> > + *
> > + * Mode 2: When requesting the driver to return the
> > + *	partitions information:
> > + *	@uuid_str: pointer to the UUID string
> > + *	@parts_size: pointer to the size of the SPs information buffer in bytes
> > + *	@buffer: pointer to SPs information buffer
> > + *		(allocated by the client).
> > + *		The buffer will be filled by the driver
> > + *
> > + * This function queries the secure partition data from
> > + * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
> > + * FF-A function to query the partition information from secure world.
> > + *
> > + * A client of the FF-A driver should know the UUID of the service it wants to
> > + * access. It should use the UUID to request the FF-A driver to provide the
> > + * partition(s) information of the service. The FF-A driver uses
> > + * PARTITION_INFO_GET to obtain this information. This is implemented through
> > + * ffa_get_partitions_info function.
> > + * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
> > + * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
> > + * They are not saved (already done). We only update the UUID in the cached area.
> > + * This assumes that partitions data does not change in the secure world.
> > + * Otherwise u-boot will have an outdated partition data. The benefit of caching
> > + * the information in the FF-A driver is to accommodate discovery after
> > + * ExitBootServices().
> > + *
> > + * When invoked through a client request, ffa_get_partitions_info should be
> > + * called twice. First call is to get from the driver the number of secure
> > + * partitions (SPs) associated to a particular UUID.
> > + * Then, the caller (client) allocates the buffer to host the SPs data and
> > + * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
> > + * buffer.
> > + *
> > + * To achieve the mechanism described above, ffa_get_partitions_info uses the
> > + * following functions:
> > + *		ffa_read_partitions_info
> > + *		ffa_query_partitions_info
> > + *
> > + * Return:
> > + *
> > + * @parts_size: When pointing to the number of partitions variable, the number is
> > + * set by the driver.
> > + * When pointing to the partitions information buffer size, the buffer will be
> > + * filled by the driver.
> 
> This is confusing, it's better if you use the same unit all the time.
> Since you below require the size to be an even multiple of sizeof(struct
> ffa_partition_info) you should perhaps use that unit.
> 
> > + *
> > + * On success 0 is returned. Otherwise, failure
> > + */
> > +static int ffa_get_partitions_info(const char *uuid_str,
> > +				   u32 *parts_size, struct ffa_partition_info *buffer)
> > +{
> > +	/*
> > +	 * fill_data:
> > +	 * 0: return the SP count
> > +	 * 1: fill SP data and return it to the caller
> > +	 * -1: undefined mode
> > +	 */
> > +	int fill_data = -1;
> 
> In the code below this is treated as a bool, it's never tested for -1,
> so you could as well make this a bool.
> 
> > +	u32 desc_idx, client_desc_idx;
> > +	struct ffa_partition_uuid part_uuid = {0};
> > +	u32 client_desc_max_cnt;
> > +	u32 parts_found = 0;
> > +
> > +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
> > +		ffa_err("no partition installed");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!uuid_str) {
> > +		ffa_err("no UUID provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!parts_size) {
> > +		ffa_err("no size/count provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
> > +		ffa_err("invalid UUID");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!buffer) {
> > +		/* Mode 1: getting the number of secure partitions */
> > +
> > +		fill_data = 0;
> > +
> > +		ffa_info("Preparing for checking partitions count");
> > +
> > +	} else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
> > +		   !(*parts_size % sizeof(struct ffa_partition_info))) {
> > +		/* Mode 2: retrieving the partitions information */
> > +
> > +		fill_data = 1;
> > +
> > +		client_desc_idx = 0;
> > +
> > +		/*
> > +		 * number of empty descriptors preallocated by the caller
> > +		 */
> > +		client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
> > +
> > +		ffa_info("Preparing for filling partitions info");
> > +
> > +	} else {
> > +		ffa_err("invalid function arguments provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_info("Searching partitions using the provided UUID");
> > +
> > +	/*
> > +	 * search in the cached partitions
> > +	 */
> > +	for (desc_idx = 0;
> > +	     desc_idx < ffa_priv_data->partitions.count;
> > +	     desc_idx++) {
> > +		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
> > +					   &part_uuid)) {
> > +			ffa_info("Partition ID %x matches the provided UUID",
> > +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> > +
> > +			parts_found++;
> > +
> > +			if (fill_data) {
> > +				/*
> > +				 * trying to fill the partition info in the input buffer
> > +				 */
> > +
> > +				if (client_desc_idx < client_desc_max_cnt) {
> > +					buffer[client_desc_idx++] =
> > +						ffa_priv_data->partitions.descs[desc_idx].info;
> > +					continue;
> > +				}
> > +
> > +				ffa_err("failed to fill the current descriptor client buffer full");
> > +				return -ENOBUFS;
> > +			}
> > +		}
> > +	}
> > +
> > +	if (!parts_found) {
> 
> By asking for a UUID never found ffa_query_partitions_info() will be
> called again, even if the rx/tx buffers needed are not available any
> longer. Since you populate the cache in ffa_probe() below, perhaps it
> would be better to only rely on the cache after that point.

Thanks for pointing out this.

As stated in the documentation under "Requirements for clients" paragraph:

Clients must:

- Query SPs in EFI boot time mode using the service UUID.
- Unmap RX/TX buffers before EFI runtime mode starts.

The RX/TX buffers are only available at EFI boot time. Querying partitions is
done at boot time and data is cached for future use.

So, when the RX/TX buffers are no longer available, we are at EFI
runtime. At that level querying is not allowed and ffa_get_partitions_info()
is not available. Only direct messaging is available.

At boot time, when an SP is queryed ffa_get_partitions_info() looks at
the cached information first. If the UUID is not found, it will
communicate with secure world to try getting the information.

By the way, all the previous comments on this v7 patch will be addressed in v8.

Thanks.

> 
> > +		int ret;
> > +
> > +		ffa_info("No partition found. Querying framework ...");
> > +
> > +		ret = ffa_query_partitions_info(&part_uuid, &parts_found);
> > +
> > +		if (ret == 0) {
> > +			if (!fill_data) {
> > +				*parts_size = parts_found;
> > +
> > +				ffa_info("Number of partition(s) found matching the UUID: %d",
> > +					 parts_found);
> > +			} else {
> > +				/*
> > +				 * If SPs data detected, they are already in the private data
> > +				 * structure, retry searching SP data again to return them
> > +				 *  to the caller
> > +				 */
> > +				if (parts_found)
> > +					ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
> > +				else
> > +					ret = -ENODATA;
> > +			}
> > +		}
> > +
> > +		return ret;
> > +	}
> > +
> > +	/* partition(s) found */
> > +	if (!fill_data)
> > +		*parts_size = parts_found;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_cache_partitions_info - Queries and saves all secure partitions data
> > + *
> > + * This function invokes FFA_PARTITION_INFO_GET FF-A
> > + * function to query from secure world all partitions information.
> > + *
> > + * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
> > + * All installed partitions information are returned. We cache them in the
> > + * resident private data structure and we keep the UUID field empty
> > + * (in FF-A 1.0 UUID is not provided by the partition descriptor)
> > + *
> > + * This function is called at the device probing level.
> > + * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_cache_partitions_info(void)
> > +{
> > +	return ffa_query_partitions_info(NULL, NULL);
> > +}
> > +
> > +/**
> > + * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> > + * @dst_part_id: destination partition ID
> > + * @msg: pointer to the message data preallocated by the client (in/out)
> > + * @is_smc64: select 64-bit or 32-bit FF-A ABI
> > + *
> > + * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * FF-A functions.
> > + *
> > + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> > + * The response from the secure partition is handled by reading the
> > + * FFA_MSG_SEND_DIRECT_RESP arguments.
> > + *
> > + * The maximum size of the data that can be exchanged is 40 bytes which is
> > + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> > + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg, bool is_smc64)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +	u64 req_mode, resp_mode;
> > +
> > +	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
> > +		return -EINVAL;
> > +
> > +	/* No partition installed */
> > +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
> > +		return -ENODEV;
> 
> This check isn't needed. What if the partition ID is known by other
> means?

I'm happy to remove this check. I'd like to add a comment explaining
what the other means are. Could you please explain what are they ?

> 
> > +
> > +	if (is_smc64) {
> > +		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
> > +		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
> > +	} else {
> > +		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
> > +		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
> > +	}
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = req_mode,
> > +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
> > +				PREP_PART_ENDPOINT_ID(dst_part_id),
> > +			.a2 = 0,
> > +			.a3 = msg->data0,
> > +			.a4 = msg->data1,
> > +			.a5 = msg->data2,
> > +			.a6 = msg->data3,
> > +			.a7 = msg->data4,
> > +			}, &res);
> > +
> > +	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
> > +		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RUN),
> > +			.a1 = res.a1,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		/* Message sent with no response */
> > +		return 0;
> > +	}
> > +
> > +	if (res.a0 == resp_mode) {
> > +		/*
> > +		 * Message sent with response
> > +		 * extract the return data
> > +		 */
> > +		msg->data0 = res.a3;
> > +		msg->data1 = res.a4;
> > +		msg->data2 = res.a5;
> > +		msg->data3 = res.a6;
> > +		msg->data4 = res.a7;
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * __arm_ffa_fn_smc - 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 low level SMC assembly function
> > + *
> > + * Return: void
> > + */
> > +void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
> > +{
> > +	arm_smccc_1_2_smc(&args, res);
> > +}
> > +
> > +/**
> > + * ffa_set_smc_conduit - Set the SMC conduit
> > + *
> > + * This function selects the SMC conduit by setting the driver invoke function
> > + * to SMC assembly function
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_set_smc_conduit(void)
> > +{
> > +	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
> > +
> > +	if (!ffa_priv_data->invoke_ffa_fn) {
> > +		ffa_err("failure to set the invoke function");
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_info("Conduit is SMC");
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_set_bus_ops - Set the bus driver operations
> > + *
> > + * Setting the driver callbacks.
> > + *
> > + */
> > +static void ffa_set_bus_ops(void)
> > +{
> > +	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
> > +	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
> > +	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
> > +}
> > +
> > +/**
> > + * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
> > + * @dev:	the arm_ffa device
> > + *
> > + * This function creates the main data structure embedding all the driver data.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_alloc_prvdata(struct udevice *dev)
> > +{
> > +	if (!dev) {
> > +		ffa_err("no udevice found");
> > +		return -ENODEV;
> > +	}
> > +
> > +	/* The device is registered with the DM. Let's create the driver main data structure*/
> > +
> > +	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
> > +	if (!ffa_priv_data) {
> > +		ffa_err("can not allocate the driver main data structure");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	ffa_priv_data->dev = dev;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_probe - The driver probe function
> > + * @dev:	the arm_ffa device
> > + *
> > + * Probing is done at boot time and triggered by the uclass device discovery.
> > + * At probe level the following actions are done:
> > + *	- setting the conduit
> > + *	- querying the FF-A framework version
> > + *	- querying from secure world the u-boot endpoint ID
> > + *	- querying from secure world the supported features of FFA_RXTX_MAP
> > + *	- mapping the RX/TX buffers
> > + *	- querying from secure world all the partitions information
> > + *
> > + * All data queried from secure world is saved in the resident private data structure.
> > + *
> > + * The probe will fail if either FF-A framework is not detected or the
> > + * FF-A requests are not behaving correctly. This ensures that the
> > + * driver is not installed and its operations are not exported to the clients.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_probe(struct udevice *dev)
> > +{
> > +	int ret;
> > +
> > +	ret = ffa_alloc_prvdata(dev);
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ffa_set_bus_ops();
> > +
> > +	ret = ffa_set_smc_conduit();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_version();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_endpoint_id();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_rxtx_map_features();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_map_rxtx_buffers();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_cache_partitions_info();
> > +	if (ret != 0) {
> > +		ffa_free_rxtx_buffers();
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_remove - The driver remove function
> > + * @dev:	the arm_ffa device
> > + * When the device is about to be removed ,  unmap the RX/TX buffers and free the memory
> > + * Return:
> > + *
> > + * 0 on success.
> > + */
> > +static int ffa_remove(struct udevice *dev)
> > +{
> > +	ffa_info("removing the device");
> > +
> > +	ffa_unmap_rxtx_buffers();
> > +
> > +	if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
> > +		ffa_free_rxtx_buffers();
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_unbind - The driver unbind function
> > + * @dev:	the arm_ffa device
> > + * After the device is removed and memory freed the device is unbound
> > + * Return:
> > + *
> > + * 0 on success.
> > + */
> > +static int ffa_unbind(struct udevice *dev)
> > +{
> > +	ffa_info("unbinding the device , private data already released");
> > +
> > +	ffa_priv_data = NULL;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_bus_ops_get - bus driver operations getter
> > + *
> > + * Return:
> > + * This function returns a pointer to the driver operations structure
> > + */
> > +const struct ffa_bus_ops *ffa_bus_ops_get(void)
> > +{
> > +	return &ffa_priv_data->ffa_ops;
> > +}
> > +
> > +/**
> > + * ffa_bus_prvdata_get - bus driver private data getter
> > + *
> > + * Return:
> > + * This function returns a pointer to the main private data structure
> > + */
> > +struct ffa_prvdata **ffa_bus_prvdata_get(void)
> 
> Why a pointer to a pointer, isn't "struct ffa_prvdata *" enough?

Because ffa_priv_data is a pointer. ffa_bus_prvdata_get() returns an
address of a pointer so the returned type should be struct ffa_prvdata
**

Otherwise, a compiler warning:

drivers/firmware/arm-ffa/core.c: In function ‘ffa_bus_prvdata_get’:
drivers/firmware/arm-ffa/core.c:1278:9: warning: return from incompatible pointer type [-Wincompatible-pointer-types]
  return &ffa_priv_data;
         ^~~~~~~~~~~~~~

> 
> > +{
> > +	return &ffa_priv_data;
> > +}
> > +
> > +/**
> > + * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
> > + *
> > + * 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 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.
> > + * All FF-A clients should use the arm_ffa device to use the FF-A transport.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_bus_discover(void)
> > +{
> > +	int ret = 0;
> > +
> > +	if (!ffa_priv_data)
> > +		ret = ffa_device_get();
> > +
> > +	return ret;
> > +}
> > +
> > +/**
> > + * Declaring the arm_ffa driver under UCLASS_FFA
> > + */
> > +
> > +U_BOOT_DRIVER(arm_ffa) = {
> > +	.name		= FFA_DRV_NAME,
> > +	.id		= UCLASS_FFA,
> > +	.probe		= ffa_probe,
> > +	.remove		= ffa_remove,
> > +	.unbind		= ffa_unbind,
> > +};
> > diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> > new file mode 100644
> > index 0000000000..b0c8a18926
> > --- /dev/null
> > +++ b/include/arm_ffa.h
> > @@ -0,0 +1,93 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_H
> > +#define __ARM_FFA_H
> > +
> > +#include <linux/printk.h>
> > +
> > +/*
> > + * This header is public. It can be used by clients to access
> > + * data structures and definitions they need
> > + */
> > +
> > +/*
> > + * Macros for displaying logs
> > + */
> > +
> > +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +
> > +/*
> > + * struct ffa_partition_info - Partition information descriptor
> > + * @id:	Partition ID
> > + * @exec_ctxt:	Execution context count
> > + * @properties:	Partition properties
> > + *
> > + * Data structure containing information about partitions instantiated in the system
> > + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> > + */
> > +struct  __packed ffa_partition_info {
> > +	u16 id;
> > +	u16 exec_ctxt;
> > +/* partition supports receipt of direct requests */
> > +#define FFA_PARTITION_DIRECT_RECV	BIT(0)
> > +/* partition can send direct requests. */
> > +#define FFA_PARTITION_DIRECT_SEND	BIT(1)
> > +/* partition can send and receive indirect messages. */
> > +#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
> > +	u32 properties;
> > +};
> 
> Perhaps this has been discussed before. Why is this packed? Is it to allow
> unaligned access or to be sure that there is not implicitly added padding?
> The Linux kernel does seem to need it.

When not using __packed the compiler will add paddings.
ffa_partition_info structure is used for reading SP information
from the secure world.

The issue arises when the non secure world and the secure world
have different architectures (Aarch64 vs Aarch32) or different
endianess. In these cases, the data will be corrupted.

I think we need to use __packed for all the comms structures.

I'm aware ffa_partition_info in the kernel is not packed. I'm happy
to remove __packed from here to align it with Linux.

But please share your thoughts about the padding issues when
working with different architecures/endianess.

Thanks.

> 
> > +
> > +/*
> > + * struct ffa_send_direct_data - Data structure hosting the data
> > + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * @data0-4:	Data read/written from/to x3-x7 registers
> > + *
> > + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> > + * or read from FFA_MSG_SEND_DIRECT_RESP
> > + */
> > +
> > +/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
> > +struct __packed ffa_send_direct_data {
> > +	unsigned long data0; /* w3/x3 */
> > +	unsigned long data1; /* w4/x4 */
> > +	unsigned long data2; /* w5/x5 */
> > +	unsigned long data3; /* w6/x6 */
> > +	unsigned long data4; /* w7/x7 */
> > +};
> 
> Why is this __packed? It seems unnecessary.

Yes, in this specific case packing is not necessary. I'll remove this in
v8.

> 
> Cheers,
> Jens
> 
> > +
> > +/**
> > + * struct ffa_bus_ops - The driver operations structure
> > + * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
> > + * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
> > + * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
> > + *
> > + * The data structure providing all the operations supported by the driver.
> > + * This structure is EFI runtime resident.
> > + */
> > +struct ffa_bus_ops {
> > +	int (*partition_info_get)(const char *uuid_str,
> > +				  u32 *parts_size, struct ffa_partition_info *buffer);
> > +	int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg, bool is_smc64);
> > +	int (*rxtx_unmap)(void);
> > +};
> > +
> > +/**
> > + * The device driver and the Uclass driver public functions
> > + */
> > +
> > +/**
> > + * ffa_bus_ops_get - driver operations getter
> > + */
> > +const struct ffa_bus_ops *ffa_bus_ops_get(void);
> > +
> > +/**
> > + * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
> > + */
> > +int ffa_bus_discover(void);
> > +
> > +#endif
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index 4b2c323452..fb59d4f356 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -4,6 +4,9 @@
> >   *
> >   * (C) Copyright 2012
> >   * Pavel Herrmann <morpheus.ibis@gmail.com>
> > + *
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  
> >  #ifndef _DM_UCLASS_ID_H
> > @@ -55,6 +58,7 @@ enum uclass_id {
> >  	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
> >  	UCLASS_ETH,		/* Ethernet device */
> >  	UCLASS_ETH_PHY,		/* Ethernet PHY device */
> > +	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
> >  	UCLASS_FIRMWARE,	/* Firmware */
> >  	UCLASS_FPGA,		/* FPGA device */
> >  	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
> > -- 
> > 2.17.1
> > 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v7 00/10] introduce Arm FF-A support
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
                                                         ` (9 preceding siblings ...)
  2022-11-07 19:20                                       ` [PATCH v7 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
@ 2022-11-11 14:42                                       ` Abdellatif El Khlifi
  2022-11-22 13:17                                       ` [PATCH v8 " Abdellatif El Khlifi
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-11 14:42 UTC (permalink / raw)
  To: ilias.apalodimas, jens.wiklander, abdellatif.elkhlifi; +Cc: u-boot, nd

On Mon, Nov 07, 2022 at 07:20:45PM +0000, Abdellatif El Khlifi wrote:
> Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [7].
> 
> FF-A describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World. These interfaces enable a pair of
> software sandboxes to communicate with each other. A sandbox aka partition could
> be a VM in the Normal or Secure world, an application in S-EL0, or a
> Trusted OS in S-EL1.
> 
> The FF-A transport is implemented as a data bus and a core driver is provided.
> 
> This implementation of the specification provides support for Aarch64.
> 
> The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> 
>     - Discover the presence of secure partitions (SPs) of interest
>     - Access an SP's service through communication protocols
>       e.g. EFI MM communication protocol
> 
> The FF-A support provides the following features:
> 
>     - Being generic by design and can be used by any Arm 64-bit platform
>     - The FF-A core driver
>     - The FF-A bus is discoverable on demand at runtime
>     - The driver provides driver operations to be used by clients to access the FF-A bus
>     - FF-A driver can be compiled and used without EFI
>     - Support for SMCCCv1.2 x0-x17 registers
>     - Support for SMC32 calling convention
>     - Support for 32-bit and 64-bit FF-A direct messaging
>     - A new command called armffa is provided as an example of how to access the
>       FF-A bus
>     - An FF-A Sandbox driver is provided with test cases
>     - Support for FF-A MM communication (compatible with EFI boot time)
>     - Enabling FF-A and MM communication in Corstone1000 platform
> 
> For more details about the FF-A core driver please refer to [8].
> 
> Please find at [9] an example of the expected boot logs when enabling
> FF-A support for a platform. In this example the platform is
> Corstone1000. But it can be any Arm 64-bit platform.
> 
> Changelog of the major changes:
> ===========================
> 
> v7:
> 
> * add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
> * set the MM door bell event to use 64-bit direct messaging
> * issue a compile time error when one of these macros are not found :
>   FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
> * make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
>   by using same APIs

Hi Ilias, Jens,

After addressing your current comments for v7 patchset, which patches are you happy with so I could
add the Reviewed-by: to the commits logs ?

Cheers

> 
> v6: [6]
> 
> * remove clearing x0-x17 registers after SMC calls
> * drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
> * drop discovery from initcalls (discovery will be on demand by FF-A users)
> * add FF-A runtime discovery at MM communication level
> * update the documentation and move it to doc/arch/arm64.ffa.rst
> 
> v5: [5]
> 
> * move changelogs in each commit to the changes section
> 
> v4: [4]
> 
> * add FF-A support README (doc/README.ffa.drv)
> * improving error handling by mapping the FF-A errors to standard errors
>   and logs
> * replacing panics with an error log
> * align sandbox driver and tests with the new FF-A driver interfaces
>  and new way of error handling
> * use the new FF-A driver interfaces for MM communication
> * discover MM partitions at runtime
> * copy FF-A driver private data to EFI runtime section at
>   ExitBootServices()
> * moving the FF-A driver work to drivers/firmware/arm-ffa
> * improving features discovery in FFA_FEATURES
> * add remove/unbind functions to the FF-A core device
> * improve how the driver behaves when bus discovery is done more than
>   once
> * move clearing x0-x17 registers code into a new macro like done in
>    the linux kernel
> * enable EFI MM communication for the Corstone1000 platform
> 
> v3: [3]
> 
> * port x0-x17 registers support from linux kernel as defined by
>    SMCCCv1.2
> * align the interfaces of the u-boot FF-A driver with those in the linux
>    FF-A driver
> * remove the FF-A helper layer
> * make the u-boot FF-A driver independent from EFI
> * provide an optional config that enables copying the driver data to
>    EFI runtime section at ExitBootServices service
> * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
> * update armffa command with the new driver interfaces
> 
> v2  [2]:
> 
> * make FF-A bus discoverable using device_{bind, probe} APIs
> * remove device tree support
> 
> v1  [1]:
> 
> * introduce FF-A bus driver with device tree support
> * introduce armffa command
> * introduce FF-A Sandbox driver
> * add FF-A Sandbox test cases
> * introduce FF-A MM communication
> 
> Cheers,
> Abdellatif
> 
> [1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
> [2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
> [3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
> [4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
> [5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
> [6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
> [7]: https://developer.arm.com/documentation/den0077/latest/
> [8]: doc/arch/arm64.ffa.rst
> [9]: example of boot logs when enabling FF-A
> 
> ```
> U-Boot 2022.07 (Jul 11 2022 - 13:42:58 +0000) corstone1000 aarch64 
> ...
> [FFA] Conduit is SMC
> [FFA] FF-A driver 1.0
> FF-A framework 1.0
> [FFA] Versions are compatible 
> [FFA] endpoint ID is 0
> [FFA] Using 1 4KB page(s) for RX/TX buffers size
> [FFA] RX buffer at virtual address 0xfdf18000
> [FFA] TX buffer at virtual address 0xfdf1a000
> [FFA] RX/TX buffers mapped
> [FFA] Reading partitions data from the RX buffer
> [FFA] Partition ID 8001 : info cached
> [FFA] Partition ID 8002 : info cached
> [FFA] Partition ID 8003 : info cached
> [FFA] 3 partition(s) found and cached
> [FFA] Preparing for checking partitions count
> [FFA] Searching partitions using the provided UUID
> [FFA] No partition found. Querying framework ...
> [FFA] Reading partitions data from the RX buffer
> [FFA] Number of partition(s) found matching the UUID: 1
> EFI: Pre-allocating 1 partition(s) info structures
> [FFA] Preparing for filling partitions info
> [FFA] Searching partitions using the provided UUID
> [FFA] Partition ID 8003 matches the provided UUID
> EFI: MM partition ID 0x8003
> ...
> Booting /MemoryMapped(0x0,0x88200000,0xf00000)
> EFI stub: Booting Linux Kernel...
> EFI stub: Using DTB from configuration table
> EFI stub: Exiting boot services...
> [FFA] Freeing RX/TX buffers
> Booting Linux on physical CPU 0x0000000000 [0x410fd040]
> Linux version 5.19.9-yocto-standard (oe-user@oe-host)
> (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld
> (GNU Binutils) 2.39.0.20220819) #1 SMP PREEMPT Wed Sep 21 20:11:18 UTC 2022
> ```
> 
> 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>
> Cc: Achin Gupta <achin.gupta@arm.com>
> Cc: Drew Reed <Drew.Reed@arm.com>
> Cc: Vishnu Banavath <vishnu.banavath@arm.com>
> Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>
> 
> Abdellatif El Khlifi (10):
>   arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
>   lib: uuid: introduce uuid_str_to_le_bin function
>   arm_ffa: introduce Arm FF-A low-level driver
>   arm_ffa: efi: unmap RX/TX buffers
>   arm_ffa: introduce armffa command
>   arm_ffa: introduce the FF-A Sandbox driver
>   arm_ffa: introduce Sandbox test cases for UCLASS_FFA
>   arm_ffa: introduce armffa command Sandbox test
>   arm_ffa: efi: introduce FF-A MM communication
>   arm_ffa: efi: corstone1000: enable MM communication
> 
>  MAINTAINERS                                   |   11 +
>  arch/arm/cpu/armv8/smccc-call.S               |   53 +
>  arch/arm/lib/asm-offsets.c                    |   14 +
>  cmd/Kconfig                                   |   10 +
>  cmd/Makefile                                  |    2 +
>  cmd/armffa.c                                  |  239 +++
>  configs/corstone1000_defconfig                |    4 +
>  configs/sandbox64_defconfig                   |    2 +
>  configs/sandbox_defconfig                     |    2 +
>  doc/arch/arm64.ffa.rst                        |  218 +++
>  doc/arch/index.rst                            |    1 +
>  doc/arch/sandbox.rst                          |    1 +
>  drivers/Kconfig                               |    2 +
>  drivers/Makefile                              |    1 +
>  drivers/firmware/arm-ffa/Kconfig              |   36 +
>  drivers/firmware/arm-ffa/Makefile             |    7 +
>  drivers/firmware/arm-ffa/arm-ffa-uclass.c     |   16 +
>  drivers/firmware/arm-ffa/arm_ffa_prv.h        |  210 +++
>  drivers/firmware/arm-ffa/core.c               | 1324 +++++++++++++++++
>  drivers/firmware/arm-ffa/sandbox.c            |  659 ++++++++
>  .../firmware/arm-ffa/sandbox_arm_ffa_prv.h    |  144 ++
>  include/arm_ffa.h                             |   93 ++
>  include/configs/corstone1000.h                |    9 +
>  include/dm/uclass-id.h                        |    4 +
>  include/linux/arm-smccc.h                     |   43 +
>  include/mm_communication.h                    |    5 +
>  include/sandbox_arm_ffa.h                     |   91 ++
>  include/uuid.h                                |    8 +
>  lib/efi_loader/Kconfig                        |   14 +-
>  lib/efi_loader/efi_boottime.c                 |   13 +
>  lib/efi_loader/efi_variable_tee.c             |  269 +++-
>  lib/uuid.c                                    |   46 +
>  test/cmd/Makefile                             |    2 +
>  test/cmd/armffa.c                             |   40 +
>  test/dm/Makefile                              |    2 +
>  test/dm/ffa.c                                 |  394 +++++
>  36 files changed, 3983 insertions(+), 6 deletions(-)
>  create mode 100644 cmd/armffa.c
>  create mode 100644 doc/arch/arm64.ffa.rst
>  create mode 100644 drivers/firmware/arm-ffa/Kconfig
>  create mode 100644 drivers/firmware/arm-ffa/Makefile
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
>  create mode 100644 drivers/firmware/arm-ffa/core.c
>  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/arm_ffa.h
>  create mode 100644 include/sandbox_arm_ffa.h
>  create mode 100644 test/cmd/armffa.c
>  create mode 100644 test/dm/ffa.c
> 
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v7 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2022-11-07 19:20                                       ` [PATCH v7 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
  2022-11-08 13:47                                         ` Ilias Apalodimas
@ 2022-11-11 17:02                                         ` Anders Dellien
  2022-11-14 10:11                                           ` Abdellatif El Khlifi
  1 sibling, 1 reply; 478+ messages in thread
From: Anders Dellien @ 2022-11-11 17:02 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: nd, u-boot

Hi Abdel,

From: U-Boot <u-boot-bounces@lists.denx.de> on behalf of Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Date: Monday, 7 November 2022 at 19:22
To: Abdellatif El Khlifi <Abdellatif.ElKhlifi@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>, Achin Gupta <Achin.Gupta@arm.com>, ilias.apalodimas@linaro.org <ilias.apalodimas@linaro.org>, jens.wiklander@linaro.org <jens.wiklander@linaro.org>, nd <nd@arm.com>, sjg@chromium.org <sjg@chromium.org>, trini@konsulko.com <trini@konsulko.com>, u-boot@lists.denx.de <u-boot@lists.denx.de>, Vishnu Banavath <Vishnu.Banavath@arm.com>, Xueliang Zhong <Xueliang.Zhong@arm.com>
Subject: [PATCH v7 02/10] lib: uuid: introduce uuid_str_to_le_bin function
convert UUID string to little endian binary data

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>

---

Changelog:
===============

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

include/uuid.h |  8 ++++++++
 lib/uuid.c     | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..293a8eb0a5 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,8 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +46,10 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin - Converts a UUID string to little endian binary data
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 465e1ac38f..cde5ae2bb7 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */

 #include <common.h>
@@ -346,6 +348,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
         return 0;
 }

+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:  pointer to UUID string
+ * @uuid_bin:  pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+       u16 tmp16;
+       u32 tmp32;
+       u64 tmp64;
+
+       if (!uuid_str_valid(uuid_str) || !uuid_bin)
+               return -EINVAL;
+
+       tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+       memcpy(uuid_bin, &tmp32, 4);
+
+       tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+       memcpy(uuid_bin + 4, &tmp16, 2);
+
+       tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+       memcpy(uuid_bin + 6, &tmp16, 2);
+
+       tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+       memcpy(uuid_bin + 8, &tmp16, 2);
+
+       tmp64 = cpu_to_le64(hextoul(uuid_str + 24, NULL));
+       memcpy(uuid_bin + 10, (char *)&tmp64, 6);

I think we might risk overflow here on platforms where “ulong” happens to be 32 bits.

+
+       return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
--
2.17.1

^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v7 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2022-11-11 17:02                                         ` Anders Dellien
@ 2022-11-14 10:11                                           ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-14 10:11 UTC (permalink / raw)
  To: Anders Dellien; +Cc: u-boot, nd

On Fri, Nov 11, 2022 at 05:02:26PM +0000, Anders Dellien wrote:
> Hi Abdel,
> 
> From: U-Boot <u-boot-bounces@lists.denx.de> on behalf of Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Date: Monday, 7 November 2022 at 19:22
> To: Abdellatif El Khlifi <Abdellatif.ElKhlifi@arm.com>
> Cc: Drew Reed <Drew.Reed@arm.com>, Achin Gupta <Achin.Gupta@arm.com>, ilias.apalodimas@linaro.org <ilias.apalodimas@linaro.org>, jens.wiklander@linaro.org <jens.wiklander@linaro.org>, nd <nd@arm.com>, sjg@chromium.org <sjg@chromium.org>, trini@konsulko.com <trini@konsulko.com>, u-boot@lists.denx.de <u-boot@lists.denx.de>, Vishnu Banavath <Vishnu.Banavath@arm.com>, Xueliang Zhong <Xueliang.Zhong@arm.com>
> Subject: [PATCH v7 02/10] lib: uuid: introduce uuid_str_to_le_bin function
> convert UUID string to little endian binary data
> 
> 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>
> 
> ---
> 
> Changelog:
> ===============
> 
> v7:
> 
> * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> * make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
>   by using same APIs
> 
> v4:
> 
> * rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
>   a standalone commit (the current)
> 
> v3:
> 
> * introduce ffa_uuid_str_to_bin (provided by
>   arm_ffa: introduce Arm FF-A low-level driver)
> 
> include/uuid.h |  8 ++++++++
>  lib/uuid.c     | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 54 insertions(+)
> 
> diff --git a/include/uuid.h b/include/uuid.h
> index 4a4883d3b5..293a8eb0a5 100644
> --- a/include/uuid.h
> +++ b/include/uuid.h
> @@ -2,6 +2,8 @@
>  /*
>   * Copyright (C) 2014 Samsung Electronics
>   * Przemyslaw Marczak <p.marczak@samsung.com>
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  #ifndef __UUID_H__
>  #define __UUID_H__
> @@ -44,4 +46,10 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
>  const char *uuid_guid_get_str(const unsigned char *guid_bin);
>  void gen_rand_uuid(unsigned char *uuid_bin);
>  void gen_rand_uuid_str(char *uuid_str, int str_format);
> +
> +/**
> + * uuid_str_to_le_bin - Converts a UUID string to little endian binary data
> + */
> +int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
> +
>  #endif
> diff --git a/lib/uuid.c b/lib/uuid.c
> index 465e1ac38f..cde5ae2bb7 100644
> --- a/lib/uuid.c
> +++ b/lib/uuid.c
> @@ -1,6 +1,8 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  /*
>   * Copyright 2011 Calxeda, Inc.
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
> 
>  #include <common.h>
> @@ -346,6 +348,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
>          return 0;
>  }
> 
> +/**
> + * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
> + * @uuid_str:  pointer to UUID string
> + * @uuid_bin:  pointer to allocated array for little endian output [16B]
> + *
> + * UUID string is 36 characters (36 bytes):
> + *
> + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
> + *
> + * where x is a hexadecimal character. Fields are separated by '-'s.
> + * When converting to a little endian binary UUID, the string fields are reversed.
> + *
> + * Return:
> + *
> + *    uuid_bin filled with little endian UUID data
> + *    On success 0 is returned. Otherwise, failure code.
> + */
> +int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
> +{
> +       u16 tmp16;
> +       u32 tmp32;
> +       u64 tmp64;
> +
> +       if (!uuid_str_valid(uuid_str) || !uuid_bin)
> +               return -EINVAL;
> +
> +       tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
> +       memcpy(uuid_bin, &tmp32, 4);
> +
> +       tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
> +       memcpy(uuid_bin + 4, &tmp16, 2);
> +
> +       tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
> +       memcpy(uuid_bin + 6, &tmp16, 2);
> +
> +       tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
> +       memcpy(uuid_bin + 8, &tmp16, 2);
> +
> +       tmp64 = cpu_to_le64(hextoul(uuid_str + 24, NULL));
> +       memcpy(uuid_bin + 10, (char *)&tmp64, 6);
> 
> I think we might risk overflow here on platforms where “ulong” happens to be 32 bits.

Thanks Anders, a very valid point.

I will use simple_strtoull() in place of hextoul()

I'll make the change in v8.

> 
> +
> +       return 0;
> +}
> +
>  /*
>   * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
>   *
> --
> 2.17.1

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v7 09/10] arm_ffa: efi: introduce FF-A MM communication
  2022-11-07 19:20                                       ` [PATCH v7 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2022-11-15  9:03                                         ` Ilias Apalodimas
  2022-11-22 13:37                                           ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2022-11-15  9:03 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, jens.wiklander, nd, sjg, trini, u-boot,
	vishnu.banavath, xueliang.zhong, Gowtham Suresh Kumar

Hi Abdellatif

On Mon, Nov 07, 2022 at 07:20:54PM +0000, Abdellatif El Khlifi wrote:
> Add MM communication support using FF-A transport
> 
> This feature allows accessing MM partitions services through
> EFI MM communication protocol. MM partitions such as StandAlonneMM
> or smm-gateway secure partitions which reside in secure world.
> 
> An MM shared buffer and a door bell event are used to exchange
> the data.
> 
> The data is used by EFI services such as GetVariable()/SetVariable()
> and copied from the communication buffer to the MM shared buffer.
>  
>  config EFI_MM_COMM_TEE
> -	bool "UEFI variables storage service via OP-TEE"
> -	depends on OPTEE
> +	bool "UEFI variables storage service via the trusted world"
> +	depends on OPTEE && ARM_FFA_TRANSPORT

This shouldn't rely on both.  It's either OP-TEE or FF-A

>  
> +#if (IS_ENABLED(CONFIG_OPTEE))

This separation is a bit problematic.  A user can configure bot OP-TEE and
FF-A. Those are not mutually exclusive,  but for the EFI
variables case they are.  We need a better way to isolate the compilation
choices.  Why don't we make ffa_bus_discover() return -1 if FF-A isn't
compiled in?

>  /**
>   * get_connection() - Retrieve OP-TEE session for a specific UUID.
>   *
> @@ -143,13 +176,229 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
>  
>  	return ret;
>  }
> +#endif
> +
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +
> +/**
> + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> + *
> + * Notifies the MM partition in the trusted world that
> + * data is available in the shared buffer.
> + * This is a blocking call during which trusted world has exclusive access
> + * to the MM shared buffer.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_notify_mm_sp(void)
> +{
> +	struct ffa_send_direct_data msg = {0};
> +	int ret;
> +	int sp_event_ret = -1;
> +
> +	if (!ffa_bus_ops_get())
> +		return -EINVAL;
> +
> +	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
> +
> +	ret = ffa_bus_ops_get()->sync_send_receive(mm_sp_id, &msg, 1);
> +	if (ret != 0)
> +		return ret;
> +
> +	sp_event_ret = msg.data0; /* x3 */
> +
> +	if (sp_event_ret == MM_SUCCESS)
> +		return 0;
> +
> +	/*
> +	 * Failure to notify the MM SP
> +	 */
> +
> +	return -EACCES;
> +}
> +
> +/**
> + * ffa_discover_mm_sp_id() - Query the MM partition ID
> + *
> + * Use the FF-A driver to get the MM partition ID.
> + * If multiple partitions are found, use the first one.
> + * This is a boot time function.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_discover_mm_sp_id(void)
> +{
> +	u32 count = 0, size = 0;
> +	int ret;
> +	struct ffa_partition_info *parts_info;
> +
> +	if (!ffa_bus_ops_get())
> +		return -EINVAL;
> +
> +	/*
> +	 * get from the driver the count of the SPs matching the UUID
> +	 */
> +	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &count, NULL);
> +	if (ret != 0) {
> +		log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
> +		return ret;
> +	}
> +
> +	if (!count) {
> +		log_info("EFI: No MM partition found\n");
> +		return ret;
> +	}
> +
> +	/*
> +	 * pre-allocate a buffer to be filled by the driver
> +	 * with	 ffa_partition_info structs
> +	 */
> +
> +	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
> +
> +	parts_info = calloc(count, sizeof(struct ffa_partition_info));

I prefer sizeof(*parts_info).  Same goes for all sizeof() calls.

> +	if (!parts_info)
> +		return -ENOMEM;
> +
> +	size = count * sizeof(struct ffa_partition_info);
> +
> +	/*
> +	 * ask the driver to fill the
> +	 * buffer with the SPs info
> +	 */
> +	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &size, parts_info);
> +	if (ret != 0) {

if (!ret)

 
[...]

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v7 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-11 14:36                                           ` Abdellatif El Khlifi
@ 2022-11-15 10:32                                             ` Jens Wiklander
  2022-11-22 13:33                                               ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Jens Wiklander @ 2022-11-15 10:32 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: u-boot, nd

On Fri, Nov 11, 2022 at 02:36:11PM +0000, Abdellatif El Khlifi wrote:
> On Wed, Nov 09, 2022 at 12:51:26PM +0100, Jens Wiklander wrote:
> > On Mon, Nov 07, 2022 at 07:20:48PM +0000, Abdellatif El Khlifi wrote:
[snip]
> > > +/**
> > > + * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> > > + * @dst_part_id: destination partition ID
> > > + * @msg: pointer to the message data preallocated by the client (in/out)
> > > + * @is_smc64: select 64-bit or 32-bit FF-A ABI
> > > + *
> > > + * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > > + * FF-A functions.
> > > + *
> > > + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> > > + * The response from the secure partition is handled by reading the
> > > + * FFA_MSG_SEND_DIRECT_RESP arguments.
> > > + *
> > > + * The maximum size of the data that can be exchanged is 40 bytes which is
> > > + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> > > + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > > + *
> > > + * Return:
> > > + *
> > > + * 0 on success. Otherwise, failure
> > > + */
> > > +static int ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg, bool is_smc64)
> > > +{
> > > +	ffa_value_t res = {0};
> > > +	int ffa_errno;
> > > +	u64 req_mode, resp_mode;
> > > +
> > > +	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
> > > +		return -EINVAL;
> > > +
> > > +	/* No partition installed */
> > > +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
> > > +		return -ENODEV;
> > 
> > This check isn't needed. What if the partition ID is known by other
> > means?
> 
> I'm happy to remove this check. I'd like to add a comment explaining
> what the other means are. Could you please explain what are they ?

In some systems perhaps you have well known partition ids reserved for
certain services.

> 
> > 
> > > +
> > > +	if (is_smc64) {
> > > +		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
> > > +		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
> > > +	} else {
> > > +		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
> > > +		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
> > > +	}
> > > +
> > > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > > +			.a0 = req_mode,
> > > +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
> > > +				PREP_PART_ENDPOINT_ID(dst_part_id),
> > > +			.a2 = 0,
> > > +			.a3 = msg->data0,
> > > +			.a4 = msg->data1,
> > > +			.a5 = msg->data2,
> > > +			.a6 = msg->data3,
> > > +			.a7 = msg->data4,
> > > +			}, &res);
> > > +
> > > +	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
> > > +		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > > +			.a0 = FFA_SMC_32(FFA_RUN),
> > > +			.a1 = res.a1,
> > > +			}, &res);
> > > +
> > > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > > +		/* Message sent with no response */
> > > +		return 0;
> > > +	}
> > > +
> > > +	if (res.a0 == resp_mode) {
> > > +		/*
> > > +		 * Message sent with response
> > > +		 * extract the return data
> > > +		 */
> > > +		msg->data0 = res.a3;
> > > +		msg->data1 = res.a4;
> > > +		msg->data2 = res.a5;
> > > +		msg->data3 = res.a6;
> > > +		msg->data4 = res.a7;
> > > +
> > > +		return 0;
> > > +	}
> > > +
> > > +	ffa_errno = res.a2;
> > > +	return ffa_to_std_errno(ffa_errno);
> > > +}
> > > +

[snip]

> > > +/**
> > > + * ffa_bus_prvdata_get - bus driver private data getter
> > > + *
> > > + * Return:
> > > + * This function returns a pointer to the main private data structure
> > > + */
> > > +struct ffa_prvdata **ffa_bus_prvdata_get(void)
> > 
> > Why a pointer to a pointer, isn't "struct ffa_prvdata *" enough?
> 
> Because ffa_priv_data is a pointer. ffa_bus_prvdata_get() returns an
> address of a pointer so the returned type should be struct ffa_prvdata
> **
> 
> Otherwise, a compiler warning:
> 
> drivers/firmware/arm-ffa/core.c: In function ‘ffa_bus_prvdata_get’:
> drivers/firmware/arm-ffa/core.c:1278:9: warning: return from incompatible pointer type [-Wincompatible-pointer-types]
>   return &ffa_priv_data;
>          ^~~~~~~~~~~~~~

Why not return ffa_priv_data instead?

> 
> > 
> > > +{
> > > +	return &ffa_priv_data;
> > > +}

[snip]

 > > +++ b/include/arm_ffa.h
> > > @@ -0,0 +1,93 @@
> > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > +/*
> > > + * (C) Copyright 2022 ARM Limited
> > > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > + */
> > > +
> > > +#ifndef __ARM_FFA_H
> > > +#define __ARM_FFA_H
> > > +
> > > +#include <linux/printk.h>
> > > +
> > > +/*
> > > + * This header is public. It can be used by clients to access
> > > + * data structures and definitions they need
> > > + */
> > > +
> > > +/*
> > > + * Macros for displaying logs
> > > + */
> > > +
> > > +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> > > +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> > > +
> > > +/*
> > > + * struct ffa_partition_info - Partition information descriptor
> > > + * @id:	Partition ID
> > > + * @exec_ctxt:	Execution context count
> > > + * @properties:	Partition properties
> > > + *
> > > + * Data structure containing information about partitions instantiated in the system
> > > + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> > > + */
> > > +struct  __packed ffa_partition_info {
> > > +	u16 id;
> > > +	u16 exec_ctxt;
> > > +/* partition supports receipt of direct requests */
> > > +#define FFA_PARTITION_DIRECT_RECV	BIT(0)
> > > +/* partition can send direct requests. */
> > > +#define FFA_PARTITION_DIRECT_SEND	BIT(1)
> > > +/* partition can send and receive indirect messages. */
> > > +#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
> > > +	u32 properties;
> > > +};
> > 
> > Perhaps this has been discussed before. Why is this packed? Is it to allow
> > unaligned access or to be sure that there is not implicitly added padding?
> > The Linux kernel does seem to need it.
> 
> When not using __packed the compiler will add paddings.
> ffa_partition_info structure is used for reading SP information
> from the secure world.
> 
> The issue arises when the non secure world and the secure world
> have different architectures (Aarch64 vs Aarch32) or different
> endianess. In these cases, the data will be corrupted.
> 
> I think we need to use __packed for all the comms structures.
> 
> I'm aware ffa_partition_info in the kernel is not packed. I'm happy
> to remove __packed from here to align it with Linux.
> 
> But please share your thoughts about the padding issues when
> working with different architecures/endianess.

__packed doesn't help with endianess, besides if I remember correctly
these are always expected to be little endian. But I guess that could be
a problem for another day.

I believe the layout of these structs are designed in a way that a
reasonable compiler wouldn't add padding on AArch32 or AArch64. Note
that packed does more than just force generation of inefficient code on
Arm (unaligned access), it also makes it invalid to take the address of
a member inside such a struct.

Cheers,
Jens

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver
  2022-08-01 17:20                               ` [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
  2022-08-12  7:39                                 ` Ilias Apalodimas
  2022-08-13  2:21                                 ` Simon Glass
@ 2022-11-15 15:24                                 ` Simon Glass
  2022-11-16 13:03                                   ` Abdellatif El Khlifi
  2 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2022-11-15 15:24 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: ilias.apalodimas, jens.wiklander, achin.gupta, trini, u-boot,
	vishnu.banavath, xueliang.zhong, nd

Hi,

On Mon, 1 Aug 2022 at 11:21, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
>
> The Firmware Framework for Arm A-profile processors (FF-A)
> describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World leveraging TrustZone
> technology.
>
> This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> querying the FF-A framework from the secure world.
>
> 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
>
> In u-boot FF-A design, FF-A is considered as a discoverable bus.
> The Secure World is considered as one entity to communicate with
> using the FF-A bus. FF-A communication is handled by one device and
> one instance (the bus). This FF-A driver takes care of all the
> interactions between Normal world and Secure World.
>
> The driver exports its operations to be used by upper layers.
>
> Exported operations:
>
> - partition_info_get
> - sync_send_receive
> - rxtx_unmap
>
> This implementation provides an optional feature to copy the driver data
> to EFI runtime area.
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Cc: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  MAINTAINERS                                |    6 +
>  common/board_r.c                           |    7 +
>  drivers/Kconfig                            |    2 +
>  drivers/Makefile                           |    1 +
>  drivers/arm-ffa/Kconfig                    |   33 +
>  drivers/arm-ffa/Makefile                   |    7 +
>  drivers/arm-ffa/arm-ffa-uclass.c           |   16 +
>  drivers/arm-ffa/arm_ffa_prv.h              |  219 ++++
>  drivers/arm-ffa/core.c                     | 1338 ++++++++++++++++++++
>  drivers/arm-ffa/efi_ffa_runtime_data_mgr.c |   94 ++
>  include/arm_ffa.h                          |  132 ++
>  include/dm/uclass-id.h                     |    1 +
>  include/uuid.h                             |    8 +
>  lib/efi_loader/efi_boottime.c              |   17 +
>  lib/uuid.c                                 |   65 +
>  15 files changed, 1946 insertions(+)
>  create mode 100644 drivers/arm-ffa/Kconfig
>  create mode 100644 drivers/arm-ffa/Makefile
>  create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
>  create mode 100644 drivers/arm-ffa/core.c
>  create mode 100644 drivers/arm-ffa/.c
>  create mode 100644 include/arm_ffa.h

Please add something to doc/ so people know what this is.

Since you are adding a new uclass you need a sandbox driver and tests.

The driver appears to have no operations, but there is a bus_ops. The
ops should go in the driver, I suspect, and should pass the device as
the first arg.

Can FFA_ERR_STAT_SUCCESS be 0 so you don't have to sprinkle the code with it?

Why is it using EFI things? Can this driver only be used with UEFI? I
hope not, if it is an official way of updating firmware.

Please don't add more things to board_r.c - we are trying to remove
this init over time. If it is a device it should be probed as needed.

Is there a device tree binding?

Also should this go in drivers/misc instead of creating a whole new subdir?

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-15 15:24                                 ` Simon Glass
@ 2022-11-16 13:03                                   ` Abdellatif El Khlifi
  2022-11-18 20:50                                     ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-16 13:03 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, nd

On Tue, Nov 15, 2022 at 08:24:24AM -0700, Simon Glass wrote:
> Hi,
> 
> On Mon, 1 Aug 2022 at 11:21, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
> >
> > The Firmware Framework for Arm A-profile processors (FF-A)
> > describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World leveraging TrustZone
> > technology.
> >
> > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > querying the FF-A framework from the secure world.
> >
> > 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> > and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> >
> > In u-boot FF-A design, FF-A is considered as a discoverable bus.
> > The Secure World is considered as one entity to communicate with
> > using the FF-A bus. FF-A communication is handled by one device and
> > one instance (the bus). This FF-A driver takes care of all the
> > interactions between Normal world and Secure World.
> >
> > The driver exports its operations to be used by upper layers.
> >
> > Exported operations:
> >
> > - partition_info_get
> > - sync_send_receive
> > - rxtx_unmap
> >
> > This implementation provides an optional feature to copy the driver data
> > to EFI runtime area.
> >
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Cc: Tom Rini <trini@konsulko.com>
> > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > Cc: Jens Wiklander <jens.wiklander@linaro.org>
> > ---
> >  MAINTAINERS                                |    6 +
> >  common/board_r.c                           |    7 +
> >  drivers/Kconfig                            |    2 +
> >  drivers/Makefile                           |    1 +
> >  drivers/arm-ffa/Kconfig                    |   33 +
> >  drivers/arm-ffa/Makefile                   |    7 +
> >  drivers/arm-ffa/arm-ffa-uclass.c           |   16 +
> >  drivers/arm-ffa/arm_ffa_prv.h              |  219 ++++
> >  drivers/arm-ffa/core.c                     | 1338 ++++++++++++++++++++
> >  drivers/arm-ffa/efi_ffa_runtime_data_mgr.c |   94 ++
> >  include/arm_ffa.h                          |  132 ++
> >  include/dm/uclass-id.h                     |    1 +
> >  include/uuid.h                             |    8 +
> >  lib/efi_loader/efi_boottime.c              |   17 +
> >  lib/uuid.c                                 |   65 +
> >  15 files changed, 1946 insertions(+)
> >  create mode 100644 drivers/arm-ffa/Kconfig
> >  create mode 100644 drivers/arm-ffa/Makefile
> >  create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
> >  create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
> >  create mode 100644 drivers/arm-ffa/core.c
> >  create mode 100644 drivers/arm-ffa/.c
> >  create mode 100644 include/arm_ffa.h
> 
> Please add something to doc/ so people know what this is.
> 
> Since you are adding a new uclass you need a sandbox driver and tests.
> 
> The driver appears to have no operations, but there is a bus_ops. The
> ops should go in the driver, I suspect, and should pass the device as
> the first arg.
> 
> Can FFA_ERR_STAT_SUCCESS be 0 so you don't have to sprinkle the code with it?
> 
> Why is it using EFI things? Can this driver only be used with UEFI? I
> hope not, if it is an official way of updating firmware.
> 
> Please don't add more things to board_r.c - we are trying to remove
> this init over time. If it is a device it should be probed as needed.
> 
> Is there a device tree binding?
> 
> Also should this go in drivers/misc instead of creating a whole new subdir?

Hi Simon, thanks for reviewing.

All the above comments have already been addressed in the new versions
of the patchset. Please refer to the latest version v7 [1].

By the way I'd like to highlight the following:

- The FF-A driver documentation is at doc/arch/arm64.ffa.rst, please
  refer to it since it provides helpful details about the FF-A support
  in U-Boot
- The patchset comes with Sandbox driver and tests [2]
- The driver has operations defined in struct ffa_bus_ops (include/arm_ffa.h).
  ffa_bus_ops_get() gets the ops. All these are in the driver (drivers/firmware/arm-ffa/core.c)
- The FF-A bus has only 1 device. No multiple instances. So passing the
  device doesn't make sense in our case
- FFA_ERR_STAT_SUCCESS has been removed and replaced with 0
- The driver is independent from EFI and can be compiled without EFI
- FF-A bus discovery has been removed from the initcall level (board_r.c)
  Discovery is done on demand. Clients can call ffa_bus_discover() when
  they want to use the FF-A bus. As an example of how clients initiate
  discovery please refer to the FF-A MM comms client [3].
- As done in the Linux kernel, the FF-A bus doesn't have a device tree
  binding since there is no peripheral associated with FF-A. At the
  early stages of this patchset, we double checked with the device tree
  maintainer and the decision was no device tree for FF-A
- The links below are from the U-Boot mailing list mirror in lore.kernel.org

Cheers.

[1]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20221107192055.21669-7-abdellatif.elkhlifi@arm.com/
     https://lore.kernel.org/all/20221107192055.21669-8-abdellatif.elkhlifi@arm.com/
     https://lore.kernel.org/all/20221107192055.21669-9-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20221107192055.21669-10-abdellatif.elkhlifi@arm.com/
> 
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-16 13:03                                   ` Abdellatif El Khlifi
@ 2022-11-18 20:50                                     ` Simon Glass
  2022-11-22 13:49                                       ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2022-11-18 20:50 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: u-boot, nd

Hi,

On Wed, 16 Nov 2022 at 06:03, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> On Tue, Nov 15, 2022 at 08:24:24AM -0700, Simon Glass wrote:
> > Hi,
> >
> > On Mon, 1 Aug 2022 at 11:21, Abdellatif El Khlifi
> > <abdellatif.elkhlifi@arm.com> wrote:
> > >
> > > Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
> > >
> > > The Firmware Framework for Arm A-profile processors (FF-A)
> > > describes interfaces (ABIs) that standardize communication
> > > between the Secure World and Normal World leveraging TrustZone
> > > technology.
> > >
> > > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > > querying the FF-A framework from the secure world.
> > >
> > > 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> > > and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> > >
> > > In u-boot FF-A design, FF-A is considered as a discoverable bus.
> > > The Secure World is considered as one entity to communicate with
> > > using the FF-A bus. FF-A communication is handled by one device and
> > > one instance (the bus). This FF-A driver takes care of all the
> > > interactions between Normal world and Secure World.
> > >
> > > The driver exports its operations to be used by upper layers.
> > >
> > > Exported operations:
> > >
> > > - partition_info_get
> > > - sync_send_receive
> > > - rxtx_unmap
> > >
> > > This implementation provides an optional feature to copy the driver data
> > > to EFI runtime area.
> > >
> > > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > Cc: Tom Rini <trini@konsulko.com>
> > > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > > Cc: Jens Wiklander <jens.wiklander@linaro.org>
> > > ---
> > >  MAINTAINERS                                |    6 +
> > >  common/board_r.c                           |    7 +
> > >  drivers/Kconfig                            |    2 +
> > >  drivers/Makefile                           |    1 +
> > >  drivers/arm-ffa/Kconfig                    |   33 +
> > >  drivers/arm-ffa/Makefile                   |    7 +
> > >  drivers/arm-ffa/arm-ffa-uclass.c           |   16 +
> > >  drivers/arm-ffa/arm_ffa_prv.h              |  219 ++++
> > >  drivers/arm-ffa/core.c                     | 1338 ++++++++++++++++++++
> > >  drivers/arm-ffa/efi_ffa_runtime_data_mgr.c |   94 ++
> > >  include/arm_ffa.h                          |  132 ++
> > >  include/dm/uclass-id.h                     |    1 +
> > >  include/uuid.h                             |    8 +
> > >  lib/efi_loader/efi_boottime.c              |   17 +
> > >  lib/uuid.c                                 |   65 +
> > >  15 files changed, 1946 insertions(+)
> > >  create mode 100644 drivers/arm-ffa/Kconfig
> > >  create mode 100644 drivers/arm-ffa/Makefile
> > >  create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
> > >  create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
> > >  create mode 100644 drivers/arm-ffa/core.c
> > >  create mode 100644 drivers/arm-ffa/.c
> > >  create mode 100644 include/arm_ffa.h
> >
> > Please add something to doc/ so people know what this is.
> >
> > Since you are adding a new uclass you need a sandbox driver and tests.
> >
> > The driver appears to have no operations, but there is a bus_ops. The
> > ops should go in the driver, I suspect, and should pass the device as
> > the first arg.
> >
> > Can FFA_ERR_STAT_SUCCESS be 0 so you don't have to sprinkle the code with it?
> >
> > Why is it using EFI things? Can this driver only be used with UEFI? I
> > hope not, if it is an official way of updating firmware.
> >
> > Please don't add more things to board_r.c - we are trying to remove
> > this init over time. If it is a device it should be probed as needed.
> >
> > Is there a device tree binding?
> >
> > Also should this go in drivers/misc instead of creating a whole new subdir?
>
> Hi Simon, thanks for reviewing.
>
> All the above comments have already been addressed in the new versions
> of the patchset. Please refer to the latest version v7 [1].
>
> By the way I'd like to highlight the following:
>
> - The FF-A driver documentation is at doc/arch/arm64.ffa.rst, please
>   refer to it since it provides helpful details about the FF-A support
>   in U-Boot

OK

> - The patchset comes with Sandbox driver and tests [2]

OK I suppose I saw that previously and forgot.

> - The driver has operations defined in struct ffa_bus_ops (include/arm_ffa.h).
>   ffa_bus_ops_get() gets the ops. All these are in the driver (drivers/firmware/arm-ffa/core.c)

Can you please push a tree somewhere so I can look?

> - The FF-A bus has only 1 device. No multiple instances. So passing the
>   device doesn't make sense in our case

It must still pass the device.

> - FFA_ERR_STAT_SUCCESS has been removed and replaced with 0

OK

> - The driver is independent from EFI and can be compiled without EFI

Oh, so what is ffa_copy_runtime_data() for?

> - FF-A bus discovery has been removed from the initcall level (board_r.c)

Good.

>   Discovery is done on demand. Clients can call ffa_bus_discover() when
>   they want to use the FF-A bus. As an example of how clients initiate
>   discovery please refer to the FF-A MM comms client [3].

Is there a command to do this?

> - As done in the Linux kernel, the FF-A bus doesn't have a device tree
>   binding since there is no peripheral associated with FF-A. At the
>   early stages of this patchset, we double checked with the device tree
>   maintainer and the decision was no device tree for FF-A

Sorry, but you must add one.

> - The links below are from the U-Boot mailing list mirror in lore.kernel.org

Regards,
Simon


>
> Cheers.
>
> [1]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
> [2]: https://lore.kernel.org/all/20221107192055.21669-7-abdellatif.elkhlifi@arm.com/
>      https://lore.kernel.org/all/20221107192055.21669-8-abdellatif.elkhlifi@arm.com/
>      https://lore.kernel.org/all/20221107192055.21669-9-abdellatif.elkhlifi@arm.com/
> [3]: https://lore.kernel.org/all/20221107192055.21669-10-abdellatif.elkhlifi@arm.com/
> >
> > Regards,
> > Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v8 00/10] introduce Arm FF-A support
  2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
                                                         ` (10 preceding siblings ...)
  2022-11-11 14:42                                       ` [PATCH v7 00/10] introduce Arm FF-A support Abdellatif El Khlifi
@ 2022-11-22 13:17                                       ` Abdellatif El Khlifi
  2022-11-22 13:17                                         ` [PATCH v8 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                           ` (9 more replies)
  11 siblings, 10 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong,
	Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].

FF-A describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World. These interfaces enable a pair of
software sandboxes to communicate with each other. A sandbox aka partition could
be a VM in the Normal or Secure world, an application in S-EL0, or a
Trusted OS in S-EL1.

The FF-A transport is implemented as a data bus and a core driver is provided.

This implementation of the specification provides support for Aarch64.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

    - Discover the presence of secure partitions (SPs) of interest
    - Access an SP's service through communication protocols
      e.g. EFI MM communication protocol

The FF-A support provides the following features:

    - Being generic by design and can be used by any Arm 64-bit platform
    - The FF-A core driver
    - The FF-A bus is discoverable on demand at runtime
    - The driver provides driver operations to be used by clients to access the FF-A bus
    - FF-A driver can be compiled and used without EFI
    - Support for SMCCCv1.2 x0-x17 registers
    - Support for SMC32 calling convention
    - Support for 32-bit and 64-bit FF-A direct messaging
    - A new command called armffa is provided as an example of how to access the
      FF-A bus
    - An FF-A Sandbox driver is provided with test cases
    - Support for FF-A MM communication (compatible with EFI boot time)
    - Enabling FF-A and MM communication in Corstone1000 platform as a use case

For more details about the FF-A core driver please refer to [B].

Please find at [C] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of the major changes:
===========================

v8:

* pass the FF-A bus device to the bus operations
* isolate the compilation choices between FF-A and OP-TEE
* drop OP-TEE configs from Corstone-1000 defconfig
* make ffa_get_partitions_info() second argument to be an SP count in both
  modes

v7: [7]

* add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v6: [6]

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

List of previous patches:

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
[7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/

More details:

[A]: https://developer.arm.com/documentation/den0077/latest/
[B]: doc/arch/arm64.ffa.rst
[C]: example of boot logs when enabling FF-A

```
U-Boot 2022.07 (Jul 11 2022 - 13:42:58 +0000) corstone1000 aarch64 
...
[FFA] Conduit is SMC
[FFA] FF-A driver 1.0
FF-A framework 1.0
[FFA] Versions are compatible 
[FFA] endpoint ID is 0
[FFA] Using 1 4KB page(s) for RX/TX buffers size
[FFA] RX buffer at virtual address 0xfdf18000
[FFA] TX buffer at virtual address 0xfdf1a000
[FFA] RX/TX buffers mapped
[FFA] Reading partitions data from the RX buffer
[FFA] Partition ID 8001 : info cached
[FFA] Partition ID 8002 : info cached
[FFA] Partition ID 8003 : info cached
[FFA] 3 partition(s) found and cached
[FFA] Preparing for checking partitions count
[FFA] Searching partitions using the provided UUID
[FFA] No partition found. Querying framework ...
[FFA] Reading partitions data from the RX buffer
[FFA] Number of partition(s) found matching the UUID: 1
EFI: Pre-allocating 1 partition(s) info structures
[FFA] Preparing for filling partitions info
[FFA] Searching partitions using the provided UUID
[FFA] Partition ID 8003 matches the provided UUID
EFI: MM partition ID 0x8003
...
Booting /MemoryMapped(0x0,0x88200000,0xf00000)
EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from configuration table
EFI stub: Exiting boot services...
[FFA] Freeing RX/TX buffers
Booting Linux on physical CPU 0x0000000000 [0x410fd040]
Linux version 5.19.9-yocto-standard (oe-user@oe-host)
(aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld
(GNU Binutils) 2.39.0.20220819) #1 SMP PREEMPT Wed Sep 21 20:11:18 UTC 2022
```

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>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Vishnu Banavath <vishnu.banavath@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (10):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce uuid_str_to_le_bin function
  arm_ffa: introduce Arm FF-A low-level driver
  arm_ffa: efi: unmap RX/TX buffers
  arm_ffa: introduce armffa command
  arm_ffa: introduce the FF-A Sandbox driver
  arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   11 +
 arch/arm/cpu/armv8/smccc-call.S               |   53 +
 arch/arm/lib/asm-offsets.c                    |   14 +
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    2 +
 cmd/armffa.c                                  |  237 +++
 configs/corstone1000_defconfig                |    2 +
 configs/sandbox64_defconfig                   |    2 +
 configs/sandbox_defconfig                     |    2 +
 doc/arch/arm64.ffa.rst                        |  218 +++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox/sandbox.rst                  |    1 +
 drivers/Kconfig                               |    2 +
 drivers/Makefile                              |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   36 +
 drivers/firmware/arm-ffa/Makefile             |    7 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     |   16 +
 drivers/firmware/arm-ffa/arm_ffa_prv.h        |  205 +++
 drivers/firmware/arm-ffa/core.c               | 1329 +++++++++++++++++
 drivers/firmware/arm-ffa/sandbox.c            |  659 ++++++++
 .../firmware/arm-ffa/sandbox_arm_ffa_prv.h    |  144 ++
 include/arm_ffa.h                             |   97 ++
 include/configs/corstone1000.h                |    9 +
 include/dm/uclass-id.h                        |    4 +
 include/linux/arm-smccc.h                     |   43 +
 include/mm_communication.h                    |    5 +
 include/sandbox_arm_ffa.h                     |   91 ++
 include/uuid.h                                |    8 +
 lib/efi_loader/Kconfig                        |   14 +-
 lib/efi_loader/efi_boottime.c                 |   13 +
 lib/efi_loader/efi_variable_tee.c             |  294 +++-
 lib/uuid.c                                    |   46 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   39 +
 test/dm/Makefile                              |    2 +
 test/dm/ffa.c                                 |  392 +++++
 36 files changed, 4005 insertions(+), 6 deletions(-)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/firmware/arm-ffa/core.c
 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/arm_ffa.h
 create mode 100644 include/sandbox_arm_ffa.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v8 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2022-11-22 13:17                                       ` [PATCH v8 " Abdellatif El Khlifi
@ 2022-11-22 13:17                                         ` Abdellatif El Khlifi
  2022-11-22 13:17                                         ` [PATCH v8 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
                                                           ` (8 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>

---

Changelog:
===============

v7:

* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

arch/arm/cpu/armv8/smccc-call.S | 53 +++++++++++++++++++++++++++++++++
 arch/arm/lib/asm-offsets.c      | 14 +++++++++
 include/linux/arm-smccc.h       | 43 ++++++++++++++++++++++++++
 3 files changed, 110 insertions(+)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..ec6f299bc9 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
@@ -45,3 +47,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 22fd541f9a..db6d7ed234 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,9 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -117,6 +120,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#ifdef CONFIG_ARM64
+	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..9105031d55 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +72,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v8 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2022-11-22 13:17                                       ` [PATCH v8 " Abdellatif El Khlifi
  2022-11-22 13:17                                         ` [PATCH v8 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2022-11-22 13:17                                         ` Abdellatif El Khlifi
  2022-11-23  2:09                                           ` Simon Glass
  2022-11-22 13:17                                         ` [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
                                                           ` (7 subsequent siblings)
  9 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

convert UUID string to little endian binary data

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>

---

Changelog:
===============

v8:

* use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

include/uuid.h |  8 ++++++++
 lib/uuid.c     | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..293a8eb0a5 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,8 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +46,10 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin - Converts a UUID string to little endian binary data
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 465e1ac38f..d29f561a70 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -346,6 +348,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16;
+	u32 tmp32;
+	u64 tmp64;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+	memcpy(uuid_bin, &tmp32, 4);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16));
+	memcpy(uuid_bin + 10, &tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-22 13:17                                       ` [PATCH v8 " Abdellatif El Khlifi
  2022-11-22 13:17                                         ` [PATCH v8 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2022-11-22 13:17                                         ` [PATCH v8 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2022-11-22 13:17                                         ` Abdellatif El Khlifi
  2022-11-23  2:09                                           ` Simon Glass
  2022-11-22 13:17                                         ` [PATCH v8 04/10] arm_ffa: efi: unmap RX/TX buffers Abdellatif El Khlifi
                                                           ` (6 subsequent siblings)
  9 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

In U-Boot FF-A design, FF-A is considered as a discoverable bus.
The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- partition_info_get
- sync_send_receive
- rxtx_unmap

For more details please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

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>

---

Changelog:
===============

v8:

* make ffa_get_partitions_info() second argument to be an SP count in both
  modes
* update ffa_bus_prvdata_get() to return a pointer rather than a pointer
  address
* remove packing from ffa_partition_info and ffa_send_direct_data structures
* pass the FF-A bus device to the bus operations

v7:

* add support for 32-bit direct messaging
* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* improve the declaration of error handling mapping
* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the U-Boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the U-Boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

MAINTAINERS                               |    7 +
 doc/arch/arm64.ffa.rst                    |  218 ++++
 doc/arch/index.rst                        |    1 +
 drivers/Kconfig                           |    2 +
 drivers/Makefile                          |    1 +
 drivers/firmware/arm-ffa/Kconfig          |   30 +
 drivers/firmware/arm-ffa/Makefile         |    6 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c |   16 +
 drivers/firmware/arm-ffa/arm_ffa_prv.h    |  200 ++++
 drivers/firmware/arm-ffa/core.c           | 1315 +++++++++++++++++++++
 include/arm_ffa.h                         |   97 ++
 include/dm/uclass-id.h                    |    4 +
 12 files changed, 1897 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
 create mode 100644 drivers/firmware/arm-ffa/core.c
 create mode 100644 include/arm_ffa.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 97b2f69f65..dcd32cf83a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -263,6 +263,13 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	doc/arch/arm64.ffa.rst
+F:	drivers/firmware/arm-ffa/
+F:	include/arm_ffa.h
+
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..dfcec82e45
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,218 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Driver
+===============
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software sandboxes to
+communicate with each other. A sandbox aka partition could
+be a VM in the Normal or Secure world, an application in S-EL0, or a
+Trusted OS in S-EL1.
+
+This FF-A driver implements the interfaces to communicate with partitions in
+the Secure world aka Secure partitions (SPs).
+
+The driver specifically focuses on communicating with SPs that isolate portions
+of EFI runtime services that must run in a protected environment which is
+inaccessible by the Host OS or Hypervisor. Examples of such services are
+set/get variables.
+
+FF-A driver uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+At this stage of development the FF-A driver supports EFI boot time only.
+
+Runtime support will be added in future developments.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the driver relies on FF-A specification v1.0
+and uses SMC32 calling convention which means using the first 32-bit data of the
+Xn registers.
+
+At this stage we only need the FF-A v1.0 features.
+
+The driver has been tested with OP-TEE which supports SMC32 calling convention.
+
+For more details please refer to the FF-A v1.0 spec:
+https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
+
+For more details please refer to the SMC Calling Convention v1.2 spec:
+https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+CONFIG_ARM_FFA_TRANSPORT
+    Enables the FF-A bus driver. Turn this on if you want to use FF-A
+    communication.
+
+CONFIG_SANDBOX_FFA
+    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
+    Sandbox and provides functional tests for FF-A.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction
+is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-Boot FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs in the driver.
+
+FF-A bus discovery in U-Boot
+-------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is discovered on
+demand by the clients (users).
+
+Clients can discover the FF-A bus using ffa_bus_discover() API which triggers the
+discovery process.
+
+ffa_bus_discover() creates, binds and probes the arm_ffa device using
+device_{bind, probe} APIs.
+
+The discovery process consists in communicating with secure world (or hypervisor)
+and querying specific data.
+
+The discovery process takes place during the arm_ffa device probing which is
+handled by ffa_probe().
+
+The FF-A bus discovery is successful and the bus is ready for use when these
+operations succeed:
+
+- querying the FF-A framework version
+- querying from secure world the U-Boot endpoint ID
+- querying from secure world the RX/TX mapping  features
+- mapping the RX/TX buffers
+- querying from secure world all the partitions information
+
+Discovery failure results in a probing failure and the arm_ffa device is
+destroyed.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must:
+
+- Query SPs in EFI boot time mode using the service UUID.
+- Unmap RX/TX buffers before EFI runtime mode starts.
+
+The RX/TX buffers are only available at EFI boot time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped by the user before EFI runtime mode
+starts. The driver provides a bus operation for that: rxtx_unmap()
+
+If  RX/TX buffers created by U-Boot are not unmapped and by
+consequence becoming available at EFI runtime, secure world will get confused
+about RX/TX buffers ownership (U-Boot vs kernel).
+
+When invoking FF-A direct messaging, clients should specify which ABI protocol
+they want to use (32-bit vs 64-bit). Selecting the protocol means using
+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
+The calling convention stays the same: SMC32.
+
+The bus driver layer
+------------------------------
+
+The driver comes on top of the SMCCC layer and is implemented in
+drivers/firmware/arm-ffa/core.c
+
+The driver provides the following features:
+
+- Support for the 32-bit version of the following ABIs:
+
+FFA_VERSION
+FFA_ID_GET
+FFA_FEATURES
+FFA_PARTITION_INFO_GET
+FFA_RXTX_UNMAP
+FFA_RX_RELEASE
+FFA_RUN
+FFA_ERROR
+FFA_SUCCESS
+FFA_INTERRUPT
+FFA_MSG_SEND_DIRECT_REQ
+FFA_MSG_SEND_DIRECT_RESP
+
+- Support for the 64-bit version of the following ABIs:
+
+FFA_RXTX_MAP
+FFA_MSG_SEND_DIRECT_REQ
+FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, the driver takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- The driver provides callbacks to be used by clients to access the FF-A bus:
+
+partition_info_get
+sync_send_receive
+rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+Using armffa command
+-----------------------------------
+
+armffa is an implementation defined command showcasing how to use the FF-A driver and how to invoke
+its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus
+interfaces.
+
+Usage:
+
+armffa <sub-command> <arguments>
+
+sub-commands:
+
+        getpart <partition UUID>
+
+            lists the partition(s) info
+
+        ping <partition ID>
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays the arm_ffa device info
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index b3e85f9bf3..cf1cfc9287 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 75ac149d31..ff75b7c3f8 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
 
 source "drivers/adc/Kconfig"
 
+source "drivers/firmware/arm-ffa/Kconfig"
+
 source "drivers/ata/Kconfig"
 
 source "drivers/axi/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index ac2d83af4e..d23009577e 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -112,6 +112,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..e4914b9bc7
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,30 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  This driver is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  This FF-A driver takes care of all the interactions between Normal world
+	  and Secure World.
+
+	  For more details about the FF-A driver, please refer to doc/arch/arm64.ffa.rst
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..043a8915be
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2022
+# Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com.
+
+obj-y += arm-ffa-uclass.o core.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..7d9695d289
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+UCLASS_DRIVER(ffa) = {
+	.name		= "ffa",
+	.id		= UCLASS_FFA,
+};
diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
new file mode 100644
index 0000000000..4eea7dc036
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <arm_ffa.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/arm-smccc.h>
+
+/*
+ * This header is private. It is exclusively used by the FF-A driver
+ */
+
+/* FF-A core driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* FF-A driver version definitions */
+
+#define MAJOR_VERSION_MASK		GENMASK(30, 16)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/*
+ * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
+ */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR                 = 0x60,
+	FFA_SUCCESS               = 0x61,
+	FFA_INTERRUPT             = 0x62,
+	FFA_VERSION               = 0x63,
+	FFA_FEATURES              = 0x64,
+	FFA_RX_RELEASE            = 0x65,
+	FFA_RXTX_MAP              = 0x66,
+	FFA_RXTX_UNMAP            = 0x67,
+	FFA_PARTITION_INFO_GET    = 0x68,
+	FFA_ID_GET                = 0x69,
+	FFA_RUN                   = 0x6D,
+	FFA_MSG_SEND_DIRECT_REQ   = 0x6F,
+	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
+
+	/* to be updated when adding new FFA IDs */
+	FFA_FIRST_ID              = FFA_ERROR, /* lowest number ID*/
+	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
+};
+
+enum ffa_abi_errcode {
+	NOT_SUPPORTED = 1,
+	INVALID_PARAMETERS,
+	NO_MEMORY,
+	BUSY,
+	INTERRUPTED,
+	DENIED,
+	RETRY,
+	ABORTED,
+	MAX_NUMBER_FFA_ERR
+};
+
+/* container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#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
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Data structure hosting the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	u64 rxbuf; /* virtual address */
+	u64 txbuf; /* virtual address */
+	size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * This data structure contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* virtual address */
+};
+
+/**
+ * struct ffa_prvdata - the driver private data structure
+ *
+ * @dev:	The arm_ffa device under u-boot driver model
+ * @ffa_ops:	The driver operations structure
+ * @fwk_version:	FF-A framework version
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ * @invoke_ffa_fn:	The function executing the FF-A function
+ *
+ * The driver data structure hosting all resident data.
+ */
+struct ffa_prvdata {
+	struct udevice *dev;
+	struct ffa_bus_ops ffa_ops;
+	u32 fwk_version;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+	invoke_ffa_fn_t invoke_ffa_fn;
+};
+
+/**
+ * ffa_bus_prvdata_get - bus driver private data getter
+ */
+struct ffa_prvdata *ffa_bus_prvdata_get(void);
+
+#endif
diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
new file mode 100644
index 0000000000..0b1f8e6a07
--- /dev/null
+++ b/drivers/firmware/arm-ffa/core.c
@@ -0,0 +1,1315 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include "arm_ffa_prv.h"
+#include <asm/global_data.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * The device private data structure containing all the
+ * data read from secure world
+ */
+struct ffa_prvdata *ffa_priv_data;
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	[NOT_SUPPORTED] = -EOPNOTSUPP,
+	[INVALID_PARAMETERS] = -EINVAL,
+	[NO_MEMORY] = -ENOMEM,
+	[BUSY] = -EBUSY,
+	[INTERRUPTED] = -EINTR,
+	[DENIED] = -EACCES,
+	[RETRY] = -EAGAIN,
+	[ABORTED] = -ECANCELED,
+};
+
+struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			[NO_MEMORY] =
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			[BUSY] =
+			"BUSY: RX buffer of the caller is not free",
+			[DENIED] =
+			"DENIED: Callee is not in a state to handle this request",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			[DENIED] =
+			"DENIED: Caller did not have ownership of the RX buffer",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			[NO_MEMORY] =
+			"NO_MEMORY: Not enough memory",
+			[DENIED] =
+			"DENIED: Buffer pair already registered",
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This function maps the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This function maps the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/*
+ * Driver core functions
+ */
+
+/**
+ * ffa_remove_device - removes the arm_ffa device
+ * @dev:	the device to be removed
+ *
+ * This function makes sure the arm_ffa device is removed
+ * No need to free the kmalloced data when the device is destroyed.
+ * It's automatically done by devm management by
+ * device_remove() -> device_free() -> devres_release_probe().
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_remove_device(struct udevice *dev)
+{
+	int ret;
+
+	if (!dev) {
+		ffa_err("no udevice found");
+		return -ENODEV;
+	}
+
+	ret = device_remove(dev, DM_REMOVE_NORMAL);
+	if (ret) {
+		ffa_err("unable to remove. err:%d\n", ret);
+		return ret;
+	}
+
+	ffa_info("device removed and freed");
+
+	ret = device_unbind(dev);
+	if (ret) {
+		ffa_err("unable to unbind. err:%d\n", ret);
+		return ret;
+	}
+
+	ffa_info("device unbound");
+
+	return 0;
+}
+
+/**
+ * ffa_device_get - create, bind and probe the arm_ffa device
+ * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
+ *       successfully)
+ *
+ * This function makes sure the arm_ffa device is
+ * created, bound to this driver, probed and ready to use.
+ * Arm FF-A transport is implemented through a single U-Boot
+ * device managing the FF-A bus (arm_ffa).
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_device_get(struct udevice **pdev)
+{
+	int ret;
+	struct udevice *dev = NULL;
+
+	ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
+			  &dev);
+	if (ret)
+		return ret;
+
+	/* The FF-A bus discovery succeeds when probing is successful */
+	ret = device_probe(dev);
+	if (ret) {
+		ffa_err("arm_ffa device probing failed");
+		ffa_remove_device(dev);
+		return ret;
+	}
+
+	if (pdev)
+		*pdev = dev;
+
+	return 0;
+}
+
+/**
+ * ffa_get_version - FFA_VERSION handler function
+ *
+ * This function implements FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_version(void)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
+		ffa_info("Versions are compatible ");
+
+		ffa_priv_data->fwk_version = res.a0;
+
+		return 0;
+	}
+
+	ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id - FFA_ID_GET handler function
+ *
+ * This function implements FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		ffa_info("endpoint ID is %u", ffa_priv_data->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * This function sets the minimum number of pages
+ *  in each of the RX/TX buffers in the private data structure
+ *
+ * Return:
+ *
+ * buf_4k_pages points to the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
+{
+	if (!ffa_priv_data)
+		return -EINVAL;
+
+	switch (prop_field) {
+	case RXTX_4K:
+		ffa_priv_data->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		ffa_priv_data->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		ffa_priv_data->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		ffa_err("RX/TX buffer size not supported");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ *
+ * This function implements FFA_FEATURES FF-A function
+ * to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt(res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers - frees the RX/TX buffers
+ *
+ * This  function  frees the RX/TX buffers
+ *
+ */
+static void ffa_free_rxtx_buffers(void)
+{
+	ffa_info("Freeing RX/TX buffers");
+
+	if (ffa_priv_data->pair.rxbuf) {
+		free((void *)ffa_priv_data->pair.rxbuf);
+		ffa_priv_data->pair.rxbuf = 0;
+	}
+
+	if (ffa_priv_data->pair.txbuf) {
+		free((void *)ffa_priv_data->pair.txbuf);
+		ffa_priv_data->pair.txbuf = 0;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
+ *
+ * This function is used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(void)
+{
+	u64 bytes;
+
+	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
+		 ffa_priv_data->pair.rxtx_min_pages);
+
+	bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 */
+
+	ffa_priv_data->pair.rxbuf = (u64)memalign(bytes, bytes);
+	if (!ffa_priv_data->pair.rxbuf) {
+		ffa_err("failure to allocate RX buffer");
+		return -ENOBUFS;
+	}
+
+	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
+
+	ffa_priv_data->pair.txbuf = (u64)memalign(bytes, bytes);
+	if (!ffa_priv_data->pair.txbuf) {
+		free((void *)ffa_priv_data->pair.rxbuf);
+		ffa_priv_data->pair.rxbuf = 0;
+		ffa_err("failure to allocate the TX buffer");
+		return -ENOBUFS;
+	}
+
+	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
+
+	/*
+	 * make sure the buffers are cleared before use
+	 */
+	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
+	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
+ *
+ * This function implements FFA_RXTX_MAP FF-A function
+ * to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers(void)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ret = ffa_alloc_rxtx_buffers();
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 * no need to convert from virtual to physical
+	 */
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = ffa_priv_data->pair.txbuf,
+			.a2 = ffa_priv_data->pair.rxbuf,
+			.a3 = ffa_priv_data->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_info("RX/TX buffers mapped");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers();
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
+ *	@dev: The arm_ffa bus device
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_unmap_rxtx_buffers(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers();
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
+ *
+ * This function invokes FFA_RX_RELEASE FF-A function
+ * to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer(void)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical - checks whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * This function is used by ffa_read_partitions_info to search
+ * for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+			    const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
+ *							and saves it in the private structure
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * This function reads the partitions information
+ * returned by the FFA_PARTITION_INFO_GET and saves it in the private
+ * data structure.
+ *
+ * Return:
+ *
+ * The private data structure is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
+{
+	if (!count) {
+		ffa_err("no partition detected");
+		return -ENODATA;
+	}
+
+	ffa_info("Reading partitions data from the RX buffer");
+
+	if (!part_uuid) {
+		/*
+		 * querying information of all partitions
+		 */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			ffa_err("partitions data size exceeds the RX buffer size:");
+			ffa_err("    sizes in bytes: data %llu , RX buffer %llu ",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		ffa_priv_data->partitions.descs = devm_kmalloc(ffa_priv_data->dev, data_bytes,
+							       __GFP_ZERO);
+		if (!ffa_priv_data->partitions.descs) {
+			ffa_err("cannot  allocate partitions data buffer");
+			return -ENOMEM;
+		}
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			ffa_priv_data->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			ffa_info("Partition ID %x : info cached",
+				 ffa_priv_data->partitions.descs[desc_idx].info.id);
+		}
+
+		ffa_priv_data->partitions.count = count;
+
+		ffa_info("%d partition(s) found and cached", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
+
+		/*
+		 * search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/*
+			 * search the current ID in the cached partitions
+			 */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < ffa_priv_data->partitions.count;
+			     cached_desc_idx++) {
+				/*
+				 * save the UUID
+				 */
+				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
+ *
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * This function executes the FFA_PARTITION_INFO_GET
+ * to query the partitions data. Then, it calls ffa_read_partitions_info
+ * to save the data in the private data structure.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
+			if (ret) {
+				ffa_err("failed to read partition(s) data , error (%d)", ret);
+				ffa_release_rx_buffer();
+				return -EINVAL;
+			}
+		}
+
+		/*
+		 * return the SP count (when querying using a UUID)
+		 */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer();
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
+ *
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of partitions
+ *			 The variable will be set by the driver
+ *	@buffer: NULL
+ *
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@dev: The arm_ffa bus device
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of empty partition descriptors
+ *			 The variable will be read by the driver
+ *	@buffer: pointer to SPs information buffer
+ *		(allocated by the client and contains empty @sp_count descriptors).
+ *		The buffer will be filled by the driver
+ *
+ * This function queries the secure partition data from
+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * When invoked through a client request, ffa_get_partitions_info should be
+ * called twice. First call is to get from the driver the number of secure
+ * partitions (SPs) associated to a particular UUID.
+ * Then, the caller (client) allocates the buffer to host the SPs data and
+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
+ * buffer.
+ *
+ * To achieve the mechanism described above, ffa_get_partitions_info uses the
+ * following functions:
+ *		ffa_read_partitions_info
+ *		ffa_query_partitions_info
+ *
+ * Return:
+ *
+ * @sp_count: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer size, the buffer will be
+ * filled by the driver.
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+static int ffa_get_partitions_info(struct udevice *dev, const char *uuid_str,
+				   u32 *sp_count, struct ffa_partition_info *buffer)
+{
+	/*
+	 * fill_data:
+	 * 0: return the SP count
+	 * 1: fill SP data and return it to the caller
+	 */
+	bool fill_data = 0;
+	u32 desc_idx, client_desc_idx;
+	struct ffa_partition_uuid part_uuid = {0};
+	u32 sp_found = 0;
+
+	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
+		ffa_err("no partition installed");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		ffa_err("no UUID provided");
+		return -EINVAL;
+	}
+
+	if (!sp_count) {
+		ffa_err("no size/count provided");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		ffa_err("invalid UUID");
+		return -EINVAL;
+	}
+
+	if (!buffer) {
+		/* Mode 1: getting the number of secure partitions */
+
+		fill_data = 0;
+
+		ffa_info("Preparing for checking partitions count");
+
+	} else if (*sp_count) {
+		/* Mode 2: retrieving the partitions information */
+
+		fill_data = 1;
+
+		client_desc_idx = 0;
+
+		ffa_info("Preparing for filling partitions info");
+
+	} else {
+		ffa_err("invalid function arguments provided");
+		return -EINVAL;
+	}
+
+	ffa_info("Searching partitions using the provided UUID");
+
+	/*
+	 * search in the cached partitions
+	 */
+	for (desc_idx = 0;
+	     desc_idx < ffa_priv_data->partitions.count;
+	     desc_idx++) {
+		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
+					   &part_uuid)) {
+			ffa_info("Partition ID %x matches the provided UUID",
+				 ffa_priv_data->partitions.descs[desc_idx].info.id);
+
+			sp_found++;
+
+			if (fill_data) {
+				/*
+				 * trying to fill the partition info in the input buffer
+				 */
+
+				if (client_desc_idx < *sp_count) {
+					buffer[client_desc_idx++] =
+						ffa_priv_data->partitions.descs[desc_idx].info;
+					continue;
+				}
+
+				ffa_err("failed to fill the current descriptor client buffer full");
+				return -ENOBUFS;
+			}
+		}
+	}
+
+	if (!sp_found) {
+		int ret;
+
+		ffa_info("No partition found. Querying framework ...");
+
+		ret = ffa_query_partitions_info(&part_uuid, &sp_found);
+
+		if (ret == 0) {
+			if (!fill_data) {
+				*sp_count = sp_found;
+
+				ffa_info("Number of partition(s) found matching the UUID: %d",
+					 sp_found);
+			} else {
+				/*
+				 * If SPs data detected, they are already in the private data
+				 * structure, retry searching SP data again to return them
+				 *  to the caller
+				 */
+				if (sp_found)
+					ret = ffa_get_partitions_info(dev, uuid_str, sp_count,
+								      buffer);
+				else
+					ret = -ENODATA;
+			}
+		}
+
+		return ret;
+	}
+
+	/* partition(s) found */
+	if (!fill_data)
+		*sp_count = sp_found;
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info - Queries and saves all secure partitions data
+ *
+ * This function invokes FFA_PARTITION_INFO_GET FF-A
+ * function to query from secure world all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in the
+ * resident private data structure and we keep the UUID field empty
+ * (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * This function is called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(void)
+{
+	return ffa_query_partitions_info(NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The arm_ffa bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_msg_send_direct_req(struct udevice *dev, u16 dst_part_id,
+				   struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u64 req_mode, resp_mode;
+
+	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
+		return -EINVAL;
+
+	/* No partition installed */
+	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
+		return -ENODEV;
+
+	if (is_smc64) {
+		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+	} else {
+		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
+	}
+
+	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = req_mode,
+			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == resp_mode) {
+		/*
+		 * Message sent with response
+		 * extract the return data
+		 */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * __arm_ffa_fn_smc - 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 low level SMC assembly function
+ *
+ * Return: void
+ */
+void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * ffa_set_smc_conduit - Set the SMC conduit
+ *
+ * This function selects the SMC conduit by setting the driver invoke function
+ * to SMC assembly function
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_smc_conduit(void)
+{
+	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
+
+	if (!ffa_priv_data->invoke_ffa_fn) {
+		ffa_err("failure to set the invoke function");
+		return -EINVAL;
+	}
+
+	ffa_info("Conduit is SMC");
+
+	return 0;
+}
+
+/**
+ * ffa_set_bus_ops - Set the bus driver operations
+ *
+ * Setting the driver callbacks.
+ *
+ */
+static void ffa_set_bus_ops(void)
+{
+	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
+	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
+	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
+}
+
+/**
+ * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
+ * @dev:	the arm_ffa device
+ *
+ * This function creates the main data structure embedding all the driver data.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_prvdata(struct udevice *dev)
+{
+	if (!dev) {
+		ffa_err("no udevice found");
+		return -ENODEV;
+	}
+
+	/* The device is registered with the DM. Let's create the driver main data structure*/
+
+	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
+	if (!ffa_priv_data) {
+		ffa_err("can not allocate the driver main data structure");
+		return -ENOMEM;
+	}
+
+	ffa_priv_data->dev = dev;
+
+	return 0;
+}
+
+/**
+ * ffa_probe - The driver probe function
+ * @dev:	the arm_ffa device
+ *
+ * Probing is done at boot time and triggered by the uclass device discovery.
+ * At probe level the following actions are done:
+ *	- setting the conduit
+ *	- querying the FF-A framework version
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in the resident private data structure.
+ *
+ * The probe will fail if either FF-A framework is not detected or the
+ * FF-A requests are not behaving correctly. This ensures that the
+ * driver is not installed and its operations are not exported to the clients.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = ffa_alloc_prvdata(dev);
+	if (ret != 0)
+		return ret;
+
+	ffa_set_bus_ops();
+
+	ret = ffa_set_smc_conduit();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_version();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_endpoint_id();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers();
+	if (ret != 0)
+		return ret;
+
+	ret = ffa_cache_partitions_info();
+	if (ret != 0) {
+		ffa_free_rxtx_buffers();
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_remove - The driver remove function
+ * @dev:	the arm_ffa device
+ * When the device is about to be removed ,  unmap the RX/TX buffers and free the memory
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_remove(struct udevice *dev)
+{
+	ffa_info("removing the device");
+
+	ffa_unmap_rxtx_buffers(dev);
+
+	if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
+		ffa_free_rxtx_buffers();
+
+	return 0;
+}
+
+/**
+ * ffa_unbind - The driver unbind function
+ * @dev:	the arm_ffa device
+ * After the device is removed and memory freed the device is unbound
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_unbind(struct udevice *dev)
+{
+	ffa_info("unbinding the device , private data already released");
+
+	ffa_priv_data = NULL;
+
+	return 0;
+}
+
+/**
+ * ffa_bus_ops_get - bus driver operations getter
+ *
+ * Return:
+ * This function returns a pointer to the driver operations structure
+ */
+const struct ffa_bus_ops *ffa_bus_ops_get(void)
+{
+	return &ffa_priv_data->ffa_ops;
+}
+
+/**
+ * ffa_bus_prvdata_get - bus driver private data getter
+ *
+ * Return:
+ * This function returns a pointer to the main private data structure
+ */
+struct ffa_prvdata *ffa_bus_prvdata_get(void)
+{
+	return ffa_priv_data;
+}
+
+/**
+ * ffa_bus_discover - discover FF-A bus and probe arm_ffa device
+ * @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 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.
+ * All FF-A clients should use the arm_ffa device to use the FF-A transport.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_bus_discover(struct udevice **pdev)
+{
+	int ret = 0;
+
+	if (!ffa_priv_data) {
+		ret = ffa_device_get(pdev);
+
+	return ret;
+}
+
+/**
+ * Declaring the arm_ffa driver under UCLASS_FFA
+ */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.probe		= ffa_probe,
+	.remove		= ffa_remove,
+	.unbind		= ffa_unbind,
+};
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..74b16174c2
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#ifndef __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * Macros for displaying logs
+ */
+
+#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
+#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct ffa_send_direct_data {
+	unsigned long data0; /* w3/x3 */
+	unsigned long data1; /* w4/x4 */
+	unsigned long data2; /* w5/x5 */
+	unsigned long data3; /* w6/x6 */
+	unsigned long data4; /* w7/x7 */
+};
+
+struct udevice;
+
+/**
+ * struct ffa_bus_ops - The driver operations structure
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
+				  u32 *sp_count, struct ffa_partition_info *buffer);
+	int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg,
+				 bool is_smc64);
+	int (*rxtx_unmap)(struct udevice *dev);
+};
+
+/**
+ * The device driver and the Uclass driver public functions
+ */
+
+/**
+ * ffa_bus_ops_get - driver operations getter
+ */
+const struct ffa_bus_ops *ffa_bus_ops_get(void);
+
+/**
+ * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
+ */
+int ffa_bus_discover(struct udevice **pdev);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 376f741cc2..fa08a66ac8 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,9 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -55,6 +58,7 @@ enum uclass_id {
 	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v8 04/10] arm_ffa: efi: unmap RX/TX buffers
  2022-11-22 13:17                                       ` [PATCH v8 " Abdellatif El Khlifi
                                                           ` (2 preceding siblings ...)
  2022-11-22 13:17                                         ` [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
@ 2022-11-22 13:17                                         ` Abdellatif El Khlifi
  2022-11-23  2:09                                           ` Simon Glass
  2022-11-22 13:17                                         ` [PATCH v8 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                           ` (5 subsequent siblings)
  9 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

unmap RX/TX buffers at ExitBootServices()

Unmapping the RX/TX buffers created by u-boot is needed before EFI
runtime.

At EFI runtime the linux kernel takes care of allocating its own RX/TX
buffers and registering them with the secure world.

Secure world should be using the RX/TX buffers created by the kernel.
So, RX/TX buffers created by u-boot must be unmapped.

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>

---

Changelog:
===============

v8: pass NULL device pointer to the FF-A bus operation
v7: replace debug() by log_err()

lib/efi_loader/efi_boottime.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 253f9f75ef..8949aca250 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -3,6 +3,9 @@
  * EFI application boot time services
  *
  * Copyright (c) 2016 Alexander Graf
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
@@ -23,6 +26,10 @@
 #include <asm/setjmp.h>
 #include <linux/libfdt_env.h>
 
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+#include <arm_ffa.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Task priority level */
@@ -2178,6 +2185,12 @@ 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)
+		/* 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");
+#endif
+
 	/* Patch out unsupported runtime function */
 	efi_runtime_detach();
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v8 05/10] arm_ffa: introduce armffa command
  2022-11-22 13:17                                       ` [PATCH v8 " Abdellatif El Khlifi
                                                           ` (3 preceding siblings ...)
  2022-11-22 13:17                                         ` [PATCH v8 04/10] arm_ffa: efi: unmap RX/TX buffers Abdellatif El Khlifi
@ 2022-11-22 13:17                                         ` Abdellatif El Khlifi
  2022-11-23  2:09                                           ` Simon Glass
  2022-11-22 13:17                                         ` [PATCH v8 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
                                                           ` (4 subsequent siblings)
  9 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

Provide armffa command showcasing the use of the FF-A driver

The armffa command allows to query secure partitions data from
the secure world and exchanging messages with the partitions
using 64-bit FF-A 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>

---

Changelog:
===============

v8:

* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* adapt do_ffa_dev_list() following the recent update on
  uclass_first_device/uclass_next_device functions (they return void now)
* set armffa command to use 64-bit direct messaging

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

MAINTAINERS                      |   1 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   2 +
 cmd/armffa.c                     | 237 +++++++++++++++++++++++++++++++
 drivers/firmware/arm-ffa/Kconfig |   1 +
 5 files changed, 251 insertions(+)
 create mode 100644 cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index dcd32cf83a..aa4e87d9f8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,6 +266,7 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+F:	cmd/armffa.c
 F:	doc/arch/arm64.ffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 1092fb9c91..060d87375f 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -924,6 +924,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the Arm FF-A driver
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index 2444d116c0..c600d90d39 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,8 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
 obj-$(CONFIG_CMD_AES) += aes.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..d2e8687bfb
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <arm_ffa.h>
+#include <asm/io.h>
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+
+/**
+ * do_ffa_get_singular_partition_info - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver partition_info_get operation
+ * to retrieve the data.
+ * The input UUID string is expected to be in big endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_get_singular_partition_info(struct cmd_tbl *cmdtp, int flag, int argc,
+					      char *const argv[])
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	/* Mode 1: getting the number of secure partitions */
+	ret = ffa_bus_ops_get()->partition_info_get(NULL, argv[0], &count, NULL);
+	if (ret != 0) {
+		ffa_err("Failure in querying partitions count (error code: %d)", ret);
+		return ret;
+	}
+
+	if (!count) {
+		ffa_info("No secure partition found");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with ffa_partition_info structs
+	 */
+
+	ffa_info("Pre-allocating %d partition(s) info structures", count);
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+
+	ret = ffa_bus_ops_get()->partition_info_get(NULL, argv[0], &count, parts_info);
+	if (ret != 0) {
+		ffa_err("Failure in querying partition(s) info (error code: %d)", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * SPs found , show the partition information
+	 */
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		ffa_info("Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x",
+			 parts_info[info_idx].id,
+			 parts_info[info_idx].exec_ctxt,
+			 parts_info[info_idx].properties);
+	}
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * do_ffa_msg_send_direct_req - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function sends data to the secure partition which the ID is provided
+ * as an argument. The function uses the arm_ffa driver sync_send_receive operation
+ * to send data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int  do_ffa_msg_send_direct_req(struct cmd_tbl *cmdtp, int flag, int argc,
+				char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	errno = 0;
+	part_id = strtoul(argv[0], NULL, 16);
+
+	if (errno) {
+		ffa_err("Invalid partition ID");
+		return -EINVAL;
+	}
+
+	ret = ffa_bus_ops_get()->sync_send_receive(NULL, part_id, &msg, 1);
+	if (ret == 0) {
+		u8 cnt;
+
+		ffa_info("SP response:\n[LSB]");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			ffa_info("0x%llx", ((u64 *)&msg)[cnt]);
+	} else {
+		ffa_err("Sending direct request error (%d)", ret);
+	}
+
+	return ret;
+}
+
+/**
+ *do_ffa_dev_list - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the devices belonging to the UCLASS_FFA
+ * class. Currently, one device is expected to show up: the arm_ffa device
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_dev_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev = NULL;
+	int i;
+
+	ffa_info("arm_ffa uclass entries:");
+
+	for (i = 0, uclass_first_device(UCLASS_FFA, &dev);
+	     dev;
+	     uclass_next_device(&dev), i++) {
+		ffa_info("entry %d - instance %08x, ops %08x, plat %08x",
+			 i,
+			 (u32)map_to_sysmem(dev),
+			 (u32)map_to_sysmem(dev->driver->ops),
+			 (u32)map_to_sysmem(dev_get_plat(dev)));
+	}
+
+	return 0;
+}
+
+static struct cmd_tbl armffa_commands[] = {
+	U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_get_singular_partition_info, "", ""),
+	U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_msg_send_direct_req, "", ""),
+	U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_dev_list, "", ""),
+};
+
+/**
+ * do_armffa - the armffa command main function
+ * @cmdtp:	Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function identifies which armffa subcommand to run.
+ * Then, it makes sure the arm_ffa device is probed and
+ * ready for use.
+ * Then, it runs the subcommand.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct cmd_tbl *armffa_cmd;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
+
+	argc -= 2;
+	argv += 2;
+
+	if (!armffa_cmd || argc > armffa_cmd->maxargs)
+		return CMD_RET_USAGE;
+
+	ret = ffa_bus_discover(NULL);
+	if (ret != 0)
+		return cmd_process_error(cmdtp, ret);
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
+
+	return cmd_process_error(armffa_cmd, ret);
+}
+
+U_BOOT_CMD(armffa, 4, 1, do_armffa,
+	   "Arm FF-A operations test command",
+	   "getpart <partition UUID>\n"
+	   "	 - lists the partition(s) info\n"
+	   "ping <partition ID>\n"
+	   "	 - sends a data pattern to the specified partition\n"
+	   "devlist\n"
+	   "	 - displays the arm_ffa device info\n");
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index e4914b9bc7..be4df89d23 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -4,6 +4,7 @@ config ARM_FFA_TRANSPORT
 	bool "Enable Arm Firmware Framework for Armv8-A driver"
 	depends on DM && ARM64
 	select ARM_SMCCC
+	select CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v8 06/10] arm_ffa: introduce the FF-A Sandbox driver
  2022-11-22 13:17                                       ` [PATCH v8 " Abdellatif El Khlifi
                                                           ` (4 preceding siblings ...)
  2022-11-22 13:17                                         ` [PATCH v8 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2022-11-22 13:17                                         ` Abdellatif El Khlifi
  2022-11-23  2:09                                           ` Simon Glass
  2022-11-22 13:17                                         ` [PATCH v8 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                           ` (3 subsequent siblings)
  9 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

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>

---

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/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 aa4e87d9f8..9197344df4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -270,6 +270,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 cff166b1c1..141ffd1f85 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -258,3 +258,5 @@ CONFIG_FWU_MULTI_BANK_UPDATE=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 07fe0c3a7a..a146a6bf1b 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -333,3 +333,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/sandbox.rst b/doc/arch/sandbox/sandbox.rst
index 34c4e06d9b..a42409a7b4 100644
--- a/doc/arch/sandbox/sandbox.rst
+++ b/doc/arch/sandbox/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 8949aca250..9cf089f162 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


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v8 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  2022-11-22 13:17                                       ` [PATCH v8 " Abdellatif El Khlifi
                                                           ` (5 preceding siblings ...)
  2022-11-22 13:17                                         ` [PATCH v8 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
@ 2022-11-22 13:17                                         ` Abdellatif El Khlifi
  2022-11-23  2:09                                           ` Simon Glass
  2022-11-22 13:17                                         ` [PATCH v8 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                           ` (2 subsequent siblings)
  9 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

Add functional test cases for the FF-A core driver

These tests rely on the FF-A Sandbox driver which helps in
 inspecting the FF-A core driver.

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>

---

Changelog:
===============

v8:

  * update partition_info_get() second argument to be an SP count
  * pass NULL device pointer to the FF-A bus discovery and operations

v7: set the tests to use 64-bit direct messaging

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

v1: introduce sandbox tests

MAINTAINERS      |   1 +
 test/dm/Makefile |   2 +
 test/dm/ffa.c    | 392 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 395 insertions(+)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 9197344df4..7a2cabfb2d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -271,6 +271,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/sandbox_arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 7a79b6e1a2..85e99e1c12 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# (C) Copyright 2022 ARM Limited
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -85,6 +86,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_SANDBOX_FFA) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..128d8626a7
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <dm.h>
+#include <dm/test.h>
+#include "../../drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h"
+#include <sandbox_arm_ffa.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Macros */
+
+#define LOG_MSG_SZ (100)
+#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
+
+/* Functional tests for the UCLASS_FFA */
+
+static int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
+{
+	char cmd[LOG_CMD_SZ] = {0};
+
+	console_record_reset();
+
+	snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
+	run_command(cmd, 0);
+
+	ut_assert_console_end();
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_fwk_version(struct ffa_prvdata *prvdata, struct sandbox_ffa_prvdata *sdx_prvdata,
+			     struct unit_test_state *uts)
+{
+	if (prvdata->fwk_version != sdx_prvdata->fwk_version) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: framework version: core = 0x%x , sandbox  = 0x%x", __func__,
+			 prvdata->fwk_version,
+			sdx_prvdata->fwk_version);
+
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_endpoint_id(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (prvdata->id) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: endpoint id: core = 0x%x", __func__, prvdata->id);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_core_dev(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->dev) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: core device NULL", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_sandbox_dev(struct sandbox_ffa_prvdata *sdx_prvdata, struct unit_test_state *uts)
+{
+	if (!sdx_prvdata->dev) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: sandbox device NULL", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_rxtxbuf(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	if (!prvdata->pair.rxbuf && prvdata->pair.txbuf) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = 0x%llx txbuf = 0x%llx", __func__,
+			 prvdata->pair.rxbuf,
+			 prvdata->pair.txbuf);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int check_features(struct ffa_prvdata *prvdata, struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	if (prvdata->pair.rxtx_min_pages != RXTX_4K &&
+	    prvdata->pair.rxtx_min_pages != RXTX_16K &&
+	    prvdata->pair.rxtx_min_pages != RXTX_64K) {
+		snprintf(msg,
+			 LOG_MSG_SZ,
+			 "[%s]: Error: FFA_RXTX_MAP features = 0x%lx",
+			 __func__,
+			 prvdata->pair.rxtx_min_pages);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+	{
+		if (rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	case FFA_RXTX_UNMAP:
+	{
+		if (!rxbuf_mapped)
+			return CMD_RET_SUCCESS;
+		break;
+	}
+	default:
+		return CMD_RET_FAILURE;
+	}
+
+	snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__,
+		 (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP"));
+	dm_test_ffa_log(uts, msg);
+
+	return CMD_RET_FAILURE;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	if (rxbuf_owned) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return CMD_RET_SUCCESS;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg = {0};
+	u8 cnt;
+
+	ut_assertok(ffa_bus_ops_get()->sync_send_receive(NULL, part_id, &msg, 1));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_assertok(((u64 *)&msg)[cnt] != 0xffffffffffffffff);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct sandbox_ffa_prvdata *sdx_prvdata,
+				     struct unit_test_state *uts)
+{
+	u32 count = 0;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx, exp_info_idx;
+	int ret;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(NULL, service_uuid, &count, NULL);
+	/* make sure partitions are detected */
+	ut_assertok(ret != 0);
+	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	ut_assertok(!parts_info);
+
+	/*
+	 * ask the driver to fill the buffer with the SPs info
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(NULL, service_uuid, &count, parts_info);
+	if (ret != 0) {
+		free(parts_info);
+		ut_assertok(ret != 0);
+	}
+
+	/*
+	 * SPs found , verify the partitions information
+	 */
+
+	ret = CMD_RET_FAILURE;
+
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		for (exp_info_idx = 0;
+		     exp_info_idx < sdx_prvdata->partitions.count;
+		     exp_info_idx++) {
+			if (parts_info[info_idx].id ==
+			   sdx_prvdata->partitions.descs[exp_info_idx].info.id) {
+				ret = memcmp(&parts_info[info_idx],
+					     &sdx_prvdata->partitions.descs[exp_info_idx]
+					     .info,
+					     sizeof(struct ffa_partition_info));
+				if (ret)
+					free(parts_info);
+				ut_assertok(ret != 0);
+				/* send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
+			}
+			ret = CMD_RET_SUCCESS;
+		}
+	}
+
+	free(parts_info);
+
+	/* Verify  expected partitions found in the emulated secure world*/
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+	struct ffa_sandbox_data func_data = {0};
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	int ret;
+
+	/*  test probing FF-A devices */
+	ut_assertok(ffa_bus_discover(NULL));
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+
+	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
+
+	/* make sure private data pointers are retrieved */
+	ut_assertok(prvdata == 0);
+	ut_assertok(sdx_prvdata == 0);
+
+	/* make sure dev devices created */
+	ut_assertok(check_core_dev(prvdata, uts));
+	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
+
+	/* test FFA_VERSION */
+	ut_assertok(check_fwk_version(prvdata, sdx_prvdata, uts));
+
+	/* test FFA_ID_GET */
+	ut_assertok(check_endpoint_id(prvdata, uts));
+
+	/* test FFA_FEATURES */
+	ut_assertok(check_features(prvdata, uts));
+
+	/*  test core RX/TX buffers */
+	ut_assertok(check_rxtxbuf(prvdata, uts));
+
+	/* test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_MAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc1_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc2_uuid, sdx_prvdata, uts);
+	ut_assertok(ret != CMD_RET_SUCCESS);
+
+	/* test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* test FFA_RXTX_UNMAP */
+	ut_assertok(ffa_bus_ops_get()->rxtx_unmap(NULL));
+
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_UNMAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_prvdata *prvdata = NULL;
+	struct sandbox_ffa_prvdata *sdx_prvdata = NULL;
+	struct ffa_sandbox_data func_data = {0};
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	u32 count = 0;
+	u16 part_id = 0;
+
+	/*  test probing FF-A devices */
+	ut_assertok(ffa_bus_discover(NULL));
+
+	/* get a pointer to the FF-A core and sandbox drivers private data */
+	func_data.data0 = &prvdata;
+	func_data.data0_size = sizeof(prvdata);
+	func_data.data1 = &sdx_prvdata;
+	func_data.data1_size = sizeof(sdx_prvdata);
+
+	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
+
+	/* make sure private data pointers are retrieved */
+	ut_assertok(prvdata == 0);
+	ut_assertok(sdx_prvdata == 0);
+
+	/* make sure dev devices created */
+	ut_assertok(check_core_dev(prvdata, uts));
+	ut_assertok(check_sandbox_dev(sdx_prvdata, uts));
+
+	/* query partitions count using  invalid arguments  */
+	ret = ffa_bus_ops_get()->partition_info_get(NULL, unvalid_svc_uuid, NULL, NULL);
+	ut_assertok(ret != -EINVAL);
+
+	/* query partitions count using an invalid UUID  string */
+	ret = ffa_bus_ops_get()->partition_info_get(NULL, unvalid_svc_uuid_str, &count, NULL);
+	ut_assertok(ret != -EINVAL);
+
+	/* query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_bus_ops_get()->partition_info_get(NULL, unvalid_svc_uuid, &count, NULL);
+	ut_assertok(count != 0);
+
+	/* query partitions count using a valid UUID  */
+	count = 0;
+	ret = ffa_bus_ops_get()->partition_info_get(NULL, valid_svc_uuid, &count, NULL);
+	/* make sure partitions are detected */
+	ut_assertok(ret != 0);
+	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
+
+	/* send data to an invalid partition */
+	ret = ffa_bus_ops_get()->sync_send_receive(NULL, part_id, &msg, 1);
+	ut_assertok(ret != -EINVAL);
+
+	/* send data to a valid partition */
+	part_id = prvdata->partitions.descs[0].info.id;
+	ret = ffa_bus_ops_get()->sync_send_receive(NULL, part_id, &msg, 1);
+	ut_assertok(ret != 0);
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v8 08/10] arm_ffa: introduce armffa command Sandbox test
  2022-11-22 13:17                                       ` [PATCH v8 " Abdellatif El Khlifi
                                                           ` (6 preceding siblings ...)
  2022-11-22 13:17                                         ` [PATCH v8 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2022-11-22 13:17                                         ` Abdellatif El Khlifi
  2022-11-23  2:09                                           ` Simon Glass
  2022-11-22 13:17                                         ` [PATCH v8 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
  2022-11-22 13:17                                         ` [PATCH v8 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  9 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

Add Sandbox test for the armffa command

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>

---

Changelog:
===============

v4: drop use of helper APIs

v1: introduce armffa command sandbox test

MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 39 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7a2cabfb2d..2f1684ece7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -271,6 +271,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/sandbox_arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 6dd6e81875..4c40aefb3b 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# (C) Copyright 2022 ARM Limited
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -18,5 +19,6 @@ obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PWM) += pwm.o
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_SANDBOX_FFA) += armffa.o
 endif
 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..e04363ba63
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ */
+
+#include <common.h>
+#include <dm/test.h>
+#include <sandbox_arm_ffa.h>
+#include <string.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define PING_CMD_SIZE 19
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	char ping_cmd[PING_CMD_SIZE] = {0};
+
+	ut_assertok(ffa_bus_discover(NULL));
+
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	snprintf(ping_cmd, PING_CMD_SIZE, "armffa ping 0x%x", SANDBOX_SP1_ID);
+
+	/* armffa ping <ID> */
+	ut_assertok(run_command(ping_cmd, 0));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v8 09/10] arm_ffa: efi: introduce FF-A MM communication
  2022-11-22 13:17                                       ` [PATCH v8 " Abdellatif El Khlifi
                                                           ` (7 preceding siblings ...)
  2022-11-22 13:17                                         ` [PATCH v8 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2022-11-22 13:17                                         ` Abdellatif El Khlifi
  2022-11-22 13:17                                         ` [PATCH v8 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong,
	Gowtham Suresh Kumar

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

MM communication protocol supports FF-A 64-bit direct messaging.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>

---

Changelog:
===============

v8:

* isolate the compilation choices between FF-A and OP-TEE
* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make mm_sp_svc_uuid static
* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
* improve use of unmap_sysmem() in ffa_mm_communicate()

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

include/mm_communication.h        |   5 +
 lib/efi_loader/Kconfig            |  14 +-
 lib/efi_loader/efi_variable_tee.c | 294 +++++++++++++++++++++++++++++-
 3 files changed, 307 insertions(+), 6 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..d409bed777 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,8 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +15,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index e2b643871b..c0f2603a45 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	depends on OPTEE || ARM_FFA_TRANSPORT
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..3933a24e8c 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,9 +4,12 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright (C) 2022 ARM Limited
+ *  Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #include <common.h>
+#include <dm.h>
 #include <efi.h>
 #include <efi_api.h>
 #include <efi_loader.h>
@@ -15,6 +18,36 @@
 #include <malloc.h>
 #include <mm_communication.h>
 
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+#include <arm_ffa.h>
+#include <cpu_func.h>
+#include <mapmem.h>
+
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_SIZE 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_OFFSET
+#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_OFFSET 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_ADDR 0
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+
+static const char *mm_sp_svc_uuid = MM_SP_UUID;
+
+static u16 mm_sp_id;
+
+#endif
+
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -24,6 +57,7 @@ struct mm_connection {
 	u32 session;
 };
 
+#if (IS_ENABLED(CONFIG_OPTEE))
 /**
  * get_connection() - Retrieve OP-TEE session for a specific UUID.
  *
@@ -143,13 +177,248 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 
 	return ret;
 }
+#endif
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notifies the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret = -1;
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
+
+	ret = ffa_bus_ops_get()->sync_send_receive(NULL, mm_sp_id, &msg, 1);
+	if (ret != 0)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	if (sp_event_ret == MM_SUCCESS)
+		return 0;
+
+	/*
+	 * Failure to notify the MM SP
+	 */
+
+	return -EACCES;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+
+	if (!ffa_bus_ops_get())
+		return -EINVAL;
+
+	/*
+	 * get from the driver the count of the SPs matching the UUID
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(NULL, mm_sp_svc_uuid, &count, NULL);
+	if (ret != 0) {
+		log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
+		return ret;
+	}
+
+	if (!count) {
+		log_info("EFI: No MM partition found\n");
+		return ret;
+	}
+
+	/*
+	 * pre-allocate a buffer to be filled by the driver
+	 * with	 ffa_partition_info structs
+	 */
+
+	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
+
+	parts_info = calloc(count, sizeof(*parts_info));
+	if (!parts_info)
+		return -ENOMEM;
+
+	/*
+	 * ask the driver to fill the
+	 * buffer with the SPs info
+	 */
+	ret = ffa_bus_ops_get()->partition_info_get(NULL, mm_sp_svc_uuid, &count, parts_info);
+	if (ret) {
+		log_err("EFI: Failure in querying partition(s) info (error code: %d)\n", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/*
+	 * MM SPs found , use the first one
+	 */
+
+	mm_sp_id = parts_info[0].id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	efi_status_t efi_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
+		log_err("EFI: Failure to discover MM partition ID at boot time\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = (void *)map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+	#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+	#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+
+	switch (ffa_ret) {
+	case 0:
+	{
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		efi_ret = EFI_SUCCESS;
+		break;
+	}
+	case -EINVAL:
+		efi_ret = EFI_DEVICE_ERROR;
+		break;
+	case -EPERM:
+		efi_ret = EFI_INVALID_PARAMETER;
+		break;
+	case -EACCES:
+		efi_ret = EFI_ACCESS_DENIED;
+		break;
+	case -EBUSY:
+		efi_ret = EFI_OUT_OF_RESOURCES;
+		break;
+	default:
+		efi_ret = EFI_ACCESS_DENIED;
+	}
+
+	unmap_sysmem(virt_shared_buf);
+	return efi_ret;
+}
+#endif
+
+/**
+ * select_ffa_mm_comms() - checks FF-A support availability
+ *
+ * Making sure FF-A is compiled in. If that's the case try to discover
+ * the FF-A bus.
+ *
+ * Return:
+ *
+ * 0: FF-A ready for use. Otherwise, failure
+ */
+static efi_status_t select_ffa_mm_comms(void)
+{
+	efi_status_t ret = EFI_UNSUPPORTED;
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+	ret = ffa_bus_discover(NULL);
+	if (ret)
+		ret = EFI_NOT_READY;
+#endif
+	return ret;
+}
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
@@ -162,7 +431,17 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+	ret = select_ffa_mm_comms();
+	if (ret != EFI_SUCCESS) {
+#if (IS_ENABLED(CONFIG_OPTEE))
+		ret = optee_mm_communicate(comm_buf, dsize);
+#endif
+	} else {
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+		ret = ffa_mm_communicate(comm_buf, dsize);
+#endif
+	}
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -258,6 +537,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
 		goto out;
 	}
 	*size = var_payload->size;
+
+	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
+			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
+				MM_VARIABLE_COMMUNICATE_SIZE;
+	#endif
+
 	/*
 	 * There seems to be a bug in EDK2 miscalculating the boundaries and
 	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
@@ -697,7 +983,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v8 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2022-11-22 13:17                                       ` [PATCH v8 " Abdellatif El Khlifi
                                                           ` (8 preceding siblings ...)
  2022-11-22 13:17                                         ` [PATCH v8 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2022-11-22 13:17                                         ` Abdellatif El Khlifi
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:17 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	sjg, trini, u-boot, vishnu.banavath, xueliang.zhong

turn on EFI MM communication

On corstone1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

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>

---

Changelog:
===============

v8:

* drop OP-TEE configs from Corstone-1000 defconfig

v7:

* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
  FFA_SHARED_MM_BUFFER_OFFSET
* update FFA_SHARED_MM_BUFFER_ADDR value

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

configs/corstone1000_defconfig | 2 ++
 include/configs/corstone1000.h | 9 +++++++++
 2 files changed, 11 insertions(+)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index dddfa27507..d1dc06c86c 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -52,3 +52,5 @@ CONFIG_DM_SERIAL=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760=y
 CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
index 8e0230c135..0362d29ac2 100644
--- a/include/configs/corstone1000.h
+++ b/include/configs/corstone1000.h
@@ -14,6 +14,15 @@
 
 #include <linux/sizes.h>
 
+#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
+
+/*
+ * shared buffer physical address used for communication between
+ * u-boot and the MM SP
+ */
+#define FFA_SHARED_MM_BUFFER_ADDR	0x02000000UL
+#define FFA_SHARED_MM_BUFFER_OFFSET	0
+
 #define V2M_BASE		0x80000000
 
 #define CONFIG_PL011_CLOCK	50000000
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v7 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-09 11:51                                         ` Jens Wiklander
  2022-11-11 14:36                                           ` Abdellatif El Khlifi
@ 2022-11-22 13:28                                           ` Abdellatif El Khlifi
  1 sibling, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:28 UTC (permalink / raw)
  To: Jens Wiklander; +Cc: u-boot, nd

On Wed, Nov 09, 2022 at 12:51:26PM +0100, Jens Wiklander wrote:
> On Mon, Nov 07, 2022 at 07:20:48PM +0000, Abdellatif El Khlifi wrote:
> > Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0
> > 
> > The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> > describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World leveraging TrustZone
> > technology.
> > 
> > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > querying the FF-A framework from the secure world.
> > 
> > The driver uses SMC32 calling convention which means using the first
> > 32-bit data of the Xn registers.
> > 
> > All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
> > which has 64-bit version supported.
> > 
> > Both 32-bit and 64-bit direct messaging are supported which allows both
> > 32-bit and 64-bit clients to use the FF-A bus.
> > 
> > In U-Boot FF-A design, FF-A is considered as a discoverable bus.
> > The Secure World is considered as one entity to communicate with
> > using the FF-A bus. FF-A communication is handled by one device and
> > one instance (the bus). This FF-A driver takes care of all the
> > interactions between Normal world and Secure World.
> > 
> > The driver exports its operations to be used by upper layers.
> > 
> > Exported operations:
> > 
> > - partition_info_get
> > - sync_send_receive
> > - rxtx_unmap
> > 
> > For more details please refer to the driver documentation [2].
> > 
> > [1]: https://developer.arm.com/documentation/den0077/latest/
> > [2]: doc/arch/arm64.ffa.rst
> > 
> > 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>
> > 
> > ---
> > 
> > Changelog:
> > ===============
> > 
> > v7:
> > 
> > * add support for 32-bit direct messaging
> > * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> > * improve the declaration of error handling mapping
> > * stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported
> > 
> > v6:
> > 
> > * drop use of EFI runtime support (We decided with Linaro to add this later)
> > * drop discovery from initcalls (discovery will be on demand by FF-A users)
> > * set the alignment of the RX/TX buffers to the larger translation granule size
> > * move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
> > * update the documentation and move it to doc/arch/arm64.ffa.rst
> > 
> > v4:
> > 
> > * add doc/README.ffa.drv
> > * moving the FF-A driver work to drivers/firmware/arm-ffa
> > * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
> >   #if defined by #if CONFIG_IS_ENABLED
> > * improving error handling by mapping the FF-A errors to standard errors
> >   and logs
> > * replacing panics with an error log and returning an error code
> > * improving features discovery in FFA_FEATURES by introducing
> >   rxtx_min_pages private data field
> > * add ffa_remove and ffa_unbind functions
> > * improve how the driver behaves when bus discovery is done more than
> >   once
> > 
> > v3:
> > 
> > * align the interfaces of the U-Boot FF-A driver with those in the linux
> >   FF-A driver
> > * remove the FF-A helper layer
> > * make the U-Boot FF-A driver independent from EFI
> > * provide an optional config that enables copying the driver data to EFI
> >   runtime section at ExitBootServices service
> > * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
> > 
> > v2:
> > 
> > * make FF-A bus discoverable using device_{bind, probe} APIs
> > * remove device tree support
> > 
> > v1:
> > 
> > * introduce FF-A bus driver with device tree support
> > 
> > MAINTAINERS                               |    7 +
> >  doc/arch/arm64.ffa.rst                    |  218 ++++
> >  doc/arch/index.rst                        |    1 +
> >  drivers/Kconfig                           |    2 +
> >  drivers/Makefile                          |    1 +
> >  drivers/firmware/arm-ffa/Kconfig          |   30 +
> >  drivers/firmware/arm-ffa/Makefile         |    6 +
> >  drivers/firmware/arm-ffa/arm-ffa-uclass.c |   16 +
> >  drivers/firmware/arm-ffa/arm_ffa_prv.h    |  205 ++++
> >  drivers/firmware/arm-ffa/core.c           | 1310 +++++++++++++++++++++
> >  include/arm_ffa.h                         |   93 ++
> >  include/dm/uclass-id.h                    |    4 +
> >  12 files changed, 1893 insertions(+)
> >  create mode 100644 doc/arch/arm64.ffa.rst
> >  create mode 100644 drivers/firmware/arm-ffa/Kconfig
> >  create mode 100644 drivers/firmware/arm-ffa/Makefile
> >  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
> >  create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
> >  create mode 100644 drivers/firmware/arm-ffa/core.c
> >  create mode 100644 include/arm_ffa.h
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 1cf99c1393..450b5725ce 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -263,6 +263,13 @@ F:	drivers/net/cortina_ni.h
> >  F:	drivers/net/phy/ca_phy.c
> >  F:	configs/cortina_presidio-asic-pnand_defconfig
> >  
> > +ARM FF-A
> > +M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > +S:	Maintained
> > +F:	doc/arch/arm64.ffa.rst
> > +F:	drivers/firmware/arm-ffa/
> > +F:	include/arm_ffa.h
> > +
> >  ARM FREESCALE IMX
> >  M:	Stefano Babic <sbabic@denx.de>
> >  M:	Fabio Estevam <festevam@gmail.com>
> > diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> > new file mode 100644
> > index 0000000000..dfcec82e45
> > --- /dev/null
> > +++ b/doc/arch/arm64.ffa.rst
> > @@ -0,0 +1,218 @@
> > +.. SPDX-License-Identifier: GPL-2.0+
> > +
> > +Arm FF-A Driver
> > +===============
> > +
> > +Summary
> > +-------
> > +
> > +FF-A stands for Firmware Framework for Arm A-profile processors.
> > +
> > +FF-A specifies interfaces that enable a pair of software sandboxes to
> > +communicate with each other. A sandbox aka partition could
> > +be a VM in the Normal or Secure world, an application in S-EL0, or a
> > +Trusted OS in S-EL1.
> > +
> > +This FF-A driver implements the interfaces to communicate with partitions in
> > +the Secure world aka Secure partitions (SPs).
> > +
> > +The driver specifically focuses on communicating with SPs that isolate portions
> > +of EFI runtime services that must run in a protected environment which is
> > +inaccessible by the Host OS or Hypervisor. Examples of such services are
> > +set/get variables.
> > +
> > +FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> > +
> > +- Discover the presence of SPs of interest
> > +- Access an SP's service through communication protocols
> > +  e.g. EFI MM communication protocol
> > +
> > +At this stage of development the FF-A driver supports EFI boot time only.
> > +
> > +Runtime support will be added in future developments.
> > +
> > +FF-A and SMC specifications
> > +-------------------------------------------
> > +
> > +The current implementation of the driver relies on FF-A specification v1.0
> > +and uses SMC32 calling convention which means using the first 32-bit data of the
> > +Xn registers.
> > +
> > +At this stage we only need the FF-A v1.0 features.
> > +
> > +The driver has been tested with OP-TEE which supports SMC32 calling convention.
> > +
> > +For more details please refer to the FF-A v1.0 spec:
> > +https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=
> > +
> > +Hypervisors are supported if they are configured to trap SMC calls.
> > +
> > +The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
> > +
> > +For more details please refer to the SMC Calling Convention v1.2 spec:
> > +https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
> > +
> > +Supported hardware
> > +--------------------------------
> > +
> > +Aarch64 plaforms
> > +
> > +Configuration
> > +----------------------
> > +
> > +CONFIG_ARM_FFA_TRANSPORT
> > +    Enables the FF-A bus driver. Turn this on if you want to use FF-A
> > +    communication.
> > +
> > +CONFIG_SANDBOX_FFA
> > +    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
> > +    Sandbox and provides functional tests for FF-A.
> > +
> > +FF-A ABIs under the hood
> > +---------------------------------------
> > +
> > +Invoking an FF-A ABI involves providing to the secure world/hypervisor the
> > +expected arguments from the ABI.
> > +
> > +The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction
> > +is executed.
> > +
> > +At the secure side level or hypervisor the ABI is handled at a higher exception
> > +level and the arguments are read and processed.
> > +
> > +The response is put back through x0 to x7 registers and control is given back
> > +to the U-Boot FF-A driver (non-secure world).
> > +
> > +The driver reads the response and processes it accordingly.
> > +
> > +This methodology applies to all the FF-A ABIs in the driver.
> > +
> > +FF-A bus discovery in U-Boot
> > +-------------------------------------------
> > +
> > +When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is discovered on
> > +demand by the clients (users).
> > +
> > +Clients can discover the FF-A bus using ffa_bus_discover() API which triggers the
> > +discovery process.
> > +
> > +ffa_bus_discover() creates, binds and probes the arm_ffa device using
> > +device_{bind, probe} APIs.
> > +
> > +The discovery process consists in communicating with secure world (or hypervisor)
> > +and querying specific data.
> > +
> > +The discovery process takes place during the arm_ffa device probing which is
> > +handled by ffa_probe().
> > +
> > +The FF-A bus discovery is successful and the bus is ready for use when these
> > +operations succeed:
> > +
> > +- querying the FF-A framework version
> > +- querying from secure world the U-Boot endpoint ID
> > +- querying from secure world the RX/TX mapping  features
> > +- mapping the RX/TX buffers
> > +- querying from secure world all the partitions information
> > +
> > +Discovery failure results in a probing failure and the arm_ffa device is
> > +destroyed.
> > +
> > +Requirements for clients
> > +-------------------------------------
> > +
> > +When using the FF-A bus with EFI, clients must:
> > +
> > +- Query SPs in EFI boot time mode using the service UUID.
> > +- Unmap RX/TX buffers before EFI runtime mode starts.
> > +
> > +The RX/TX buffers are only available at EFI boot time. Querying partitions is
> > +done at boot time and data is cached for future use.
> > +
> > +RX/TX buffers should be unmapped by the user before EFI runtime mode
> > +starts. The driver provides a bus operation for that: rxtx_unmap()
> > +
> > +If  RX/TX buffers created by U-Boot are not unmapped and by
> > +consequence becoming available at EFI runtime, secure world will get confused
> > +about RX/TX buffers ownership (U-Boot vs kernel).
> > +
> > +When invoking FF-A direct messaging, clients should specify which ABI protocol
> > +they want to use (32-bit vs 64-bit). Selecting the protocol means using
> > +the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> > +The calling convention stays the same: SMC32.
> > +
> > +The bus driver layer
> > +------------------------------
> > +
> > +The driver comes on top of the SMCCC layer and is implemented in
> > +drivers/firmware/arm-ffa/core.c
> > +
> > +The driver provides the following features:
> > +
> > +- Support for the 32-bit version of the following ABIs:
> > +
> > +FFA_VERSION
> > +FFA_ID_GET
> > +FFA_FEATURES
> > +FFA_PARTITION_INFO_GET
> > +FFA_RXTX_UNMAP
> > +FFA_RX_RELEASE
> > +FFA_RUN
> > +FFA_ERROR
> > +FFA_SUCCESS
> > +FFA_INTERRUPT
> > +FFA_MSG_SEND_DIRECT_REQ
> > +FFA_MSG_SEND_DIRECT_RESP
> > +
> > +- Support for the 64-bit version of the following ABIs:
> > +
> > +FFA_RXTX_MAP
> > +FFA_MSG_SEND_DIRECT_REQ
> > +FFA_MSG_SEND_DIRECT_RESP
> > +
> > +- Processing the received data from the secure world/hypervisor and caching it
> > +
> > +- Hiding from upper layers the FF-A protocol and registers details. Upper
> > +  layers focus on exchanged data, the driver takes care of how to transport
> > +  that to the secure world/hypervisor using FF-A
> > +
> > +- The driver provides callbacks to be used by clients to access the FF-A bus:
> > +
> > +partition_info_get
> > +sync_send_receive
> > +rxtx_unmap
> > +
> > +- FF-A bus discovery makes sure FF-A framework is responsive and compatible
> > +  with the driver
> > +
> > +- FF-A bus can be compiled and used without EFI
> > +
> > +Using armffa command
> > +-----------------------------------
> > +
> > +armffa is an implementation defined command showcasing how to use the FF-A driver and how to invoke
> > +its operations.
> > +
> > +This provides a guidance to the client developers on how to call the FF-A bus
> > +interfaces.
> > +
> > +Usage:
> > +
> > +armffa <sub-command> <arguments>
> > +
> > +sub-commands:
> > +
> > +        getpart <partition UUID>
> > +
> > +            lists the partition(s) info
> > +
> > +        ping <partition ID>
> > +
> > +            sends a data pattern to the specified partition
> > +
> > +        devlist
> > +
> > +            displays the arm_ffa device info
> > +
> > +Contributors
> > +------------
> > +   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > diff --git a/doc/arch/index.rst b/doc/arch/index.rst
> > index 792d9182c3..8d1ab0ad4e 100644
> > --- a/doc/arch/index.rst
> > +++ b/doc/arch/index.rst
> > @@ -8,6 +8,7 @@ Architecture-specific doc
> >  
> >     arc
> >     arm64
> > +   arm64.ffa
> >     m68k
> >     mips
> >     nios2
> > diff --git a/drivers/Kconfig b/drivers/Kconfig
> > index 8b6fead351..b06b1ae481 100644
> > --- a/drivers/Kconfig
> > +++ b/drivers/Kconfig
> > @@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
> >  
> >  source "drivers/adc/Kconfig"
> >  
> > +source "drivers/firmware/arm-ffa/Kconfig"
> > +
> >  source "drivers/ata/Kconfig"
> >  
> >  source "drivers/axi/Kconfig"
> > diff --git a/drivers/Makefile b/drivers/Makefile
> > index a1700c819d..b86c1d2a42 100644
> > --- a/drivers/Makefile
> > +++ b/drivers/Makefile
> > @@ -111,6 +111,7 @@ obj-y += iommu/
> >  obj-y += smem/
> >  obj-y += thermal/
> >  obj-$(CONFIG_TEE) += tee/
> > +obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
> >  obj-y += axi/
> >  obj-y += ufs/
> >  obj-$(CONFIG_W1) += w1/
> > diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> > new file mode 100644
> > index 0000000000..e4914b9bc7
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/Kconfig
> > @@ -0,0 +1,30 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +config ARM_FFA_TRANSPORT
> > +	bool "Enable Arm Firmware Framework for Armv8-A driver"
> > +	depends on DM && ARM64
> > +	select ARM_SMCCC
> > +	select LIB_UUID
> > +	select DEVRES
> > +	help
> > +	  The Firmware Framework for Arm A-profile processors (FF-A)
> > +	  describes interfaces (ABIs) that standardize communication
> > +	  between the Secure World and Normal World leveraging TrustZone
> > +	  technology.
> > +
> > +	  This driver is based on FF-A specification v1.0 and uses SMC32
> > +	  calling convention.
> > +
> > +	  FF-A specification:
> > +
> > +	  https://developer.arm.com/documentation/den0077/a/?lang=en
> > +
> > +	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
> > +	  The Secure World is considered as one entity to communicate with
> > +	  using the FF-A bus.
> > +	  FF-A communication is handled by one device and one instance (the bus).
> > +	  This FF-A driver takes care of all the interactions between Normal world
> > +	  and Secure World.
> > +
> > +	  For more details about the FF-A driver, please refer to doc/arch/arm64.ffa.rst
> > +
> > diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
> > new file mode 100644
> > index 0000000000..043a8915be
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/Makefile
> > @@ -0,0 +1,6 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +#
> > +# (C) Copyright 2022
> > +# Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com.
> > +
> > +obj-y += arm-ffa-uclass.o core.o
> > diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> > new file mode 100644
> > index 0000000000..7d9695d289
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> > @@ -0,0 +1,16 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <asm/global_data.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +UCLASS_DRIVER(ffa) = {
> > +	.name		= "ffa",
> > +	.id		= UCLASS_FFA,
> > +};
> > diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> > new file mode 100644
> > index 0000000000..ad7430ada9
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> > @@ -0,0 +1,205 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_PRV_H
> > +#define __ARM_FFA_PRV_H
> > +
> > +#include <arm_ffa.h>
> > +#include <linux/bitfield.h>
> > +#include <linux/bitops.h>
> > +#include <linux/arm-smccc.h>
> > +
> > +/*
> > + * This header is private. It is exclusively used by the FF-A driver
> > + */
> > +
> > +/* FF-A core driver name */
> > +#define FFA_DRV_NAME "arm_ffa"
> > +
> > +/* FF-A driver version definitions */
> > +
> > +#define MAJOR_VERSION_MASK		GENMASK(30, 16)
> > +#define MINOR_VERSION_MASK		GENMASK(15, 0)
> > +#define GET_FFA_MAJOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> > +#define GET_FFA_MINOR_VERSION(x)		\
> > +				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> > +#define PACK_VERSION_INFO(major, minor)			\
> > +	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
> > +	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> > +
> > +#define FFA_MAJOR_VERSION		(1)
> > +#define FFA_MINOR_VERSION		(0)
> > +#define FFA_VERSION_1_0		\
> > +			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> > +
> > +/* Endpoint ID mask (u-boot endpoint ID) */
> > +
> > +#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define GET_SELF_ENDPOINT_ID(x)		\
> > +			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> > +
> > +#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
> > +#define PREP_SELF_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> > +
> > +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> > +
> > +#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
> > +#define PREP_PART_ENDPOINT_ID(x)		\
> > +			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> > +
> > +/*
> > + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> > + */
> > +
> > +#define FFA_SMC(calling_convention, func_num)				\
> > +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
> > +			   ARM_SMCCC_OWNER_STANDARD, (func_num))
> > +
> > +#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> > +#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
> > +
> > +enum ffa_abis {
> > +	FFA_ERROR					= 0x60,
> > +	FFA_SUCCESS					= 0x61,
> > +	FFA_INTERRUPT				= 0x62,
> > +	FFA_VERSION					= 0x63,
> > +	FFA_FEATURES				= 0x64,
> > +	FFA_RX_RELEASE				= 0x65,
> > +	FFA_RXTX_MAP				= 0x66,
> > +	FFA_RXTX_UNMAP			= 0x67,
> > +	FFA_PARTITION_INFO_GET		= 0x68,
> > +	FFA_ID_GET					= 0x69,
> > +	FFA_RUN						= 0x6D,
> > +	FFA_MSG_SEND_DIRECT_REQ	= 0x6F,
> > +	FFA_MSG_SEND_DIRECT_RESP	= 0x70,
> 
> Strange indentation above.

Thanks, addressed in v8 patchset.

> 
> > +
> > +	/* to be updated when adding new FFA IDs */
> > +	FFA_FIRST_ID = FFA_ERROR, /* lowest number ID*/
> > +	FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
> > +};
> > +
> > +enum ffa_abi_errcode {
> > +	NOT_SUPPORTED = 1,
> > +	INVALID_PARAMETERS,
> > +	NO_MEMORY,
> > +	BUSY,
> > +	INTERRUPTED,
> > +	DENIED,
> > +	RETRY,
> > +	ABORTED,
> > +	MAX_NUMBER_FFA_ERR
> > +};
> > +
> > +/* container structure and helper macros to map between an FF-A error and relevant error log */
> > +struct ffa_abi_errmap {
> > +	char *err_str[MAX_NUMBER_FFA_ERR];
> > +};
> > +
> > +#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
> > + *
> > + */
> > +struct ffa_partition_uuid {
> > +	u32 a1; /* w1 */
> > +	u32 a2; /* w2 */
> > +	u32 a3; /* w3 */
> > +	u32 a4; /* w4 */
> > +};
> > +
> > +/**
> > + * enum ffa_rxtx_buf_sizes - minimum sizes supported
> > + * for the RX/TX buffers
> > + */
> > +enum ffa_rxtx_buf_sizes {
> > +	RXTX_4K,
> > +	RXTX_64K,
> > +	RXTX_16K
> > +};
> > +
> > +/**
> > + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> > + * @rxbuf:	virtual address of the RX buffer
> > + * @txbuf:	virtual address of the TX buffer
> > + * @rxtx_min_pages:	RX/TX buffers minimum size in pages
> > + *
> > + * Data structure hosting the virtual addresses of the mapped RX/TX buffers
> > + * These addresses are used by the FF-A functions that use the RX/TX buffers
> > + */
> > +struct ffa_rxtxpair {
> > +	u64 rxbuf; /* virtual address */
> > +	u64 txbuf; /* virtual address */
> > +	size_t rxtx_min_pages; /* minimum number of pages in each of the RX/TX buffers */
> > +};
> > +
> > +/**
> > + * struct ffa_partition_desc - the secure partition descriptor
> > + * @info:	partition information
> > + * @sp_uuid:	the secure partition UUID
> > + *
> > + * Each partition has its descriptor containing the partitions information and the UUID
> > + */
> > +struct ffa_partition_desc {
> > +	struct ffa_partition_info info;
> > +	struct ffa_partition_uuid sp_uuid;
> > +};
> > +
> > +/**
> > + * struct ffa_partitions - descriptors for all secure partitions
> > + * @count:	The number of partitions descriptors
> > + * @descs	The partitions descriptors table
> > + *
> > + * This data structure contains the partitions descriptors table
> > + */
> > +struct ffa_partitions {
> > +	u32 count;
> > +	struct ffa_partition_desc *descs; /* virtual address */
> > +};
> > +
> > +/**
> > + * struct ffa_prvdata - the driver private data structure
> > + *
> > + * @dev:	The arm_ffa device under u-boot driver model
> > + * @ffa_ops:	The driver operations structure
> > + * @fwk_version:	FF-A framework version
> > + * @id:	u-boot endpoint ID
> > + * @partitions:	The partitions descriptors structure
> > + * @pair:	The RX/TX buffers pair
> > + * @invoke_ffa_fn:	The function executing the FF-A function
> > + *
> > + * The driver data structure hosting all resident data.
> > + */
> > +struct ffa_prvdata {
> > +	struct udevice *dev;
> > +	struct ffa_bus_ops ffa_ops;
> > +	u32 fwk_version;
> > +	u16 id;
> > +	struct ffa_partitions partitions;
> > +	struct ffa_rxtxpair pair;
> > +	invoke_ffa_fn_t invoke_ffa_fn;
> > +};
> > +
> > +/**
> > + * ffa_device_get - create, bind and probe the arm_ffa device
> > + */
> > +int ffa_device_get(void);
> > +
> > +/**
> > + * ffa_bus_prvdata_get - bus driver private data getter
> > + */
> > +struct ffa_prvdata **ffa_bus_prvdata_get(void);
> > +
> > +#endif
> > diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
> > new file mode 100644
> > index 0000000000..b955e5187b
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/core.c
> > @@ -0,0 +1,1310 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include "arm_ffa_prv.h"
> > +#include <asm/global_data.h>
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <dm/device-internal.h>
> > +#include <dm/devres.h>
> > +#include <dm/root.h>
> > +#include <linux/errno.h>
> > +#include <linux/sizes.h>
> > +#include <log.h>
> > +#include <malloc.h>
> > +#include <string.h>
> > +#include <uuid.h>
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/**
> > + * The device private data structure containing all the
> > + * data read from secure world
> > + */
> > +struct ffa_prvdata *ffa_priv_data;
> > +
> > +/* Error mapping declarations */
> > +
> > +int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
> > +	[NOT_SUPPORTED] = -EOPNOTSUPP,
> > +	[INVALID_PARAMETERS] = -EINVAL,
> > +	[NO_MEMORY] = -ENOMEM,
> > +	[BUSY] = -EBUSY,
> > +	[INTERRUPTED] = -EINTR,
> > +	[DENIED] = -EACCES,
> > +	[RETRY] = -EAGAIN,
> > +	[ABORTED] = -ECANCELED,
> > +};
> > +
> > +struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
> > +		{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
> > +		{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
> > +		{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
> > +		{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +			[INVALID_PARAMETERS] =
> > +			"INVALID_PARAMETERS: Unrecognized UUID",
> > +			[NO_MEMORY] =
> > +			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
> > +			[BUSY] =
> > +			"BUSY: RX buffer of the caller is not free",
> > +			[DENIED] =
> > +			"DENIED: Callee is not in a state to handle this request",
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
> > +			{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
> > +			[INVALID_PARAMETERS] =
> > +			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
> > +			{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
> > +			[DENIED] =
> > +			"DENIED: Caller did not have ownership of the RX buffer",
> > +		},
> > +	},
> > +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
> > +			{
> > +			[NOT_SUPPORTED] =
> > +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> > +			[INVALID_PARAMETERS] =
> > +			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
> > +			[NO_MEMORY] =
> > +			"NO_MEMORY: Not enough memory",
> > +			[DENIED] =
> > +			"DENIED: Buffer pair already registered",
> > +		},
> > +	},
> > +};
> 
> Indentation above looks strange and inconsistent in some places. This
> entire approach is in my opinion a bit complicated, no big deal, if no
> one else complains I suppose it's OK.

Addressed in v8 patchset.

> 
> > +
> > +/**
> > + * ffa_to_std_errno - convert FF-A error code to standard error code
> > + * @ffa_errno:	Error code returned by the FF-A ABI
> > + *
> > + * This function maps the given FF-A error code as specified
> > + * by the spec to a u-boot standard error code.
> > + *
> > + * Return:
> > + *
> > + * The standard error code on success. . Otherwise, failure
> > + */
> > +int ffa_to_std_errno(int ffa_errno)
> > +{
> > +	int err_idx = -ffa_errno;
> > +
> > +	/* map the FF-A error code to the standard u-boot error code */
> > +	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
> > +		return ffa_to_std_errmap[err_idx];
> > +	return -EINVAL;
> > +}
> > +
> > +/**
> > + * ffa_print_error_log - print the error log corresponding to the selected FF-A ABI
> > + * @ffa_id:	FF-A ABI ID
> > + * @ffa_errno:	Error code returned by the FF-A ABI
> > + *
> > + * This function maps the FF-A error code to the error log relevant to the
> > + * selected FF-A ABI. Then the error log is printed.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. . Otherwise, failure
> > + */
> > +int ffa_print_error_log(u32 ffa_id, int ffa_errno)
> > +{
> > +	int err_idx = -ffa_errno, abi_idx = 0;
> > +
> > +	/* map the FF-A error code to the corresponding error log */
> > +
> > +	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
> > +		return -EINVAL;
> > +
> > +	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
> > +		return -EINVAL;
> > +
> > +	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
> > +	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
> > +		return -EINVAL;
> > +
> > +	if (!err_msg_map[abi_idx].err_str[err_idx])
> > +		return -EINVAL;
> > +
> > +	ffa_err("%s", err_msg_map[abi_idx].err_str[err_idx]);
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Driver core functions
> > + */
> > +
> > +/**
> > + * ffa_remove_device - removes the arm_ffa device
> > + * @dev:	the device to be removed
> > + *
> > + * This function makes sure the arm_ffa device is removed
> > + * No need to free the kmalloced data when the device is destroyed.
> > + * It's automatically done by devm management by
> > + * device_remove() -> device_free() -> devres_release_probe().
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_remove_device(struct udevice *dev)
> > +{
> > +	int ret;
> > +
> > +	if (!dev) {
> > +		ffa_err("no udevice found");
> > +		return -ENODEV;
> > +	}
> > +
> > +	ret = device_remove(dev, DM_REMOVE_NORMAL);
> > +	if (ret) {
> > +		ffa_err("unable to remove. err:%d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	ffa_info("device removed and freed");
> > +
> > +	ret = device_unbind(dev);
> > +	if (ret) {
> > +		ffa_err("unable to unbind. err:%d\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	ffa_info("device unbound");
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_device_get - create, bind and probe the arm_ffa device
> > + *
> > + * This function makes sure the arm_ffa device is
> > + * created, bound to this driver, probed and ready to use.
> > + * Arm FF-A transport is implemented through a single u-boot
> > + * device managing the FF-A bus (arm_ffa).
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_device_get(void)
> > +{
> > +	int ret;
> > +	struct udevice *dev = NULL;
> > +
> > +	ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > +			  &dev);
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* The FF-A bus discovery succeeds when probing is successful */
> > +	ret = device_probe(dev);
> > +	if (ret) {
> > +		ffa_err("arm_ffa device probing failed");
> > +		ffa_remove_device(dev);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_get_version - FFA_VERSION handler function
> > + *
> > + * This function implements FFA_VERSION FF-A function
> > + * to get from the secure world the FF-A framework version
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_version(void)
> > +{
> > +	u16 major, minor;
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
> > +			}, &res);
> > +
> > +	ffa_errno = res.a0;
> > +	if (ffa_errno < 0) {
> > +		ffa_print_error_log(FFA_VERSION, ffa_errno);
> > +		return ffa_to_std_errno(ffa_errno);
> > +	}
> > +
> > +	major = GET_FFA_MAJOR_VERSION(res.a0);
> > +	minor = GET_FFA_MINOR_VERSION(res.a0);
> > +
> > +	ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> > +		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +	if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
> > +		ffa_info("Versions are compatible ");
> > +
> > +		ffa_priv_data->fwk_version = res.a0;
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
> > +		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +	return -EPROTONOSUPPORT;
> > +}
> > +
> > +/**
> > + * ffa_get_endpoint_id - FFA_ID_GET handler function
> > + *
> > + * This function implements FFA_ID_GET FF-A function
> > + * to get from the secure world u-boot endpoint ID
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_endpoint_id(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_ID_GET),
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_priv_data->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
> > +		ffa_info("endpoint ID is %u", ffa_priv_data->id);
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +
> > +	ffa_print_error_log(FFA_ID_GET, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_set_rxtx_buffers_pages_cnt - sets the minimum number of pages in each of the RX/TX buffers
> > + * @prop_field: properties field obtained from FFA_FEATURES ABI
> > + *
> > + * This function sets the minimum number of pages
> > + *  in each of the RX/TX buffers in the private data structure
> > + *
> > + * Return:
> > + *
> > + * buf_4k_pages points to the returned number of pages
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_set_rxtx_buffers_pages_cnt(u32 prop_field)
> > +{
> > +	if (!ffa_priv_data)
> > +		return -EINVAL;
> > +
> > +	switch (prop_field) {
> > +	case RXTX_4K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 1;
> > +		break;
> > +	case RXTX_16K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 4;
> > +		break;
> > +	case RXTX_64K:
> > +		ffa_priv_data->pair.rxtx_min_pages = 16;
> > +		break;
> > +	default:
> > +		ffa_err("RX/TX buffer size not supported");
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP argument
> > + *
> > + * This function implements FFA_FEATURES FF-A function
> > + * to retrieve the FFA_RXTX_MAP features
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_get_rxtx_map_features(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_FEATURES),
> > +			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> > +		return ffa_set_rxtx_buffers_pages_cnt(res.a2);
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_FEATURES, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> > + *
> > + * This  function  frees the RX/TX buffers
> > + *
> > + */
> > +static void ffa_free_rxtx_buffers(void)
> > +{
> > +	ffa_info("Freeing RX/TX buffers");
> > +
> > +	if (ffa_priv_data->pair.rxbuf) {
> > +		free((void *)ffa_priv_data->pair.rxbuf);
> > +		ffa_priv_data->pair.rxbuf = 0;
> > +	}
> > +
> > +	if (ffa_priv_data->pair.txbuf) {
> > +		free((void *)ffa_priv_data->pair.txbuf);
> > +		ffa_priv_data->pair.txbuf = 0;
> > +	}
> > +}
> > +
> > +/**
> > + * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
> > + *
> > + * This function is used by ffa_map_rxtx_buffers to allocate
> > + * the RX/TX buffers before mapping them. The allocated memory is physically
> > + * contiguous since memalign ends up calling malloc which allocates
> > + * contiguous memory in u-boot.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_alloc_rxtx_buffers(void)
> > +{
> > +	u64 bytes;
> > +
> > +	ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
> > +		 ffa_priv_data->pair.rxtx_min_pages);
> > +
> > +	bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> > +
> > +	/*
> > +	 * The alignment of the RX and TX buffers must be equal
> > +	 * to the larger translation granule size
> > +	 */
> > +
> > +	ffa_priv_data->pair.rxbuf = (u64)memalign(bytes, bytes);
> > +	if (!ffa_priv_data->pair.rxbuf) {
> > +		ffa_err("failure to allocate RX buffer");
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("RX buffer at virtual address 0x%llx", ffa_priv_data->pair.rxbuf);
> > +
> > +	ffa_priv_data->pair.txbuf = (u64)memalign(bytes, bytes);
> > +	if (!ffa_priv_data->pair.txbuf) {
> > +		free((void *)ffa_priv_data->pair.rxbuf);
> > +		ffa_priv_data->pair.rxbuf = 0;
> > +		ffa_err("failure to allocate the TX buffer");
> > +		return -ENOBUFS;
> > +	}
> > +
> > +	ffa_info("TX buffer at virtual address 0x%llx", ffa_priv_data->pair.txbuf);
> > +
> > +	/*
> > +	 * make sure the buffers are cleared before use
> > +	 */
> > +	memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
> > +	memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
> > + *
> > + * This function implements FFA_RXTX_MAP FF-A function
> > + * to map the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_map_rxtx_buffers(void)
> > +{
> > +	int ret;
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ret = ffa_alloc_rxtx_buffers();
> > +	if (ret)
> > +		return ret;
> > +
> > +	/*
> > +	 * we need to pass the physical addresses of the RX/TX buffers
> > +	 * in u-boot physical/virtual mapping is 1:1
> > +	 * no need to convert from virtual to physical
> > +	 */
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
> > +			.a1 = ffa_priv_data->pair.txbuf,
> > +			.a2 = ffa_priv_data->pair.rxbuf,
> > +			.a3 = ffa_priv_data->pair.rxtx_min_pages,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_info("RX/TX buffers mapped");
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
> > +
> > +	ffa_free_rxtx_buffers();
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
> > + *
> > + * This function implements FFA_RXTX_UNMAP FF-A function
> > + * to unmap the RX/TX buffers
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_unmap_rxtx_buffers(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
> > +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id),
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		ffa_free_rxtx_buffers();
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
> > + *
> > + * This function invokes FFA_RX_RELEASE FF-A function
> > + * to release the ownership of the RX buffer
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_release_rx_buffer(void)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> > +		return 0;
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_uuid_are_identical - checks whether two given UUIDs are identical
> > + * @uuid1: first UUID
> > + * @uuid2: second UUID
> > + *
> > + * This function is used by ffa_read_partitions_info to search
> > + * for a UUID in the partitions descriptors table
> > + *
> > + * Return:
> > + *
> > + * 1 when UUIDs match. Otherwise, 0
> > + */
> > +bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
> > +			    const struct ffa_partition_uuid *uuid2)
> > +{
> > +	if (!uuid1 || !uuid2)
> > +		return 0;
> > +
> > +	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
> > +}
> > +
> > +/**
> > + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> > + *							and saves it in the private structure
> > + * @count: The number of partitions queried
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + *
> > + * This function reads the partitions information
> > + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> > + * data structure.
> > + *
> > + * Return:
> > + *
> > + * The private data structure is updated with the partition(s) information
> > + * 0 is returned on success. Otherwise, failure
> > + */
> > +static int ffa_read_partitions_info(u32 count, struct ffa_partition_uuid *part_uuid)
> > +{
> > +	if (!count) {
> > +		ffa_err("no partition detected");
> > +		return -ENODATA;
> > +	}
> > +
> > +	ffa_info("Reading partitions data from the RX buffer");
> > +
> > +	if (!part_uuid) {
> > +		/*
> > +		 * querying information of all partitions
> > +		 */
> > +		u64 buf_bytes;
> > +		u64 data_bytes;
> > +		u32 desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +
> > +		data_bytes = count * sizeof(struct ffa_partition_desc);
> > +
> > +		buf_bytes = ffa_priv_data->pair.rxtx_min_pages * SZ_4K;
> > +
> > +		if (data_bytes > buf_bytes) {
> > +			ffa_err("partitions data size exceeds the RX buffer size:");
> > +			ffa_err("    sizes in bytes: data %llu , RX buffer %llu ",
> > +				data_bytes,
> > +				buf_bytes);
> > +
> > +			return -ENOMEM;
> > +		}
> > +
> > +		ffa_priv_data->partitions.descs = devm_kmalloc(ffa_priv_data->dev, data_bytes,
> > +							       __GFP_ZERO);
> > +		if (!ffa_priv_data->partitions.descs) {
> > +			ffa_err("cannot  allocate partitions data buffer");
> > +			return -ENOMEM;
> > +		}
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> > +
> > +		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
> > +			ffa_priv_data->partitions.descs[desc_idx].info =
> > +				parts_info[desc_idx];
> > +
> > +			ffa_info("Partition ID %x : info cached",
> > +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> > +		}
> > +
> > +		ffa_priv_data->partitions.count = count;
> > +
> > +		ffa_info("%d partition(s) found and cached", count);
> > +
> > +	} else {
> > +		u32 rx_desc_idx, cached_desc_idx;
> > +		struct ffa_partition_info *parts_info;
> > +		u8 desc_found;
> > +
> > +		parts_info = (struct ffa_partition_info *)ffa_priv_data->pair.rxbuf;
> > +
> > +		/*
> > +		 * search for the SP IDs read from the RX buffer
> > +		 * in the already cached SPs.
> > +		 * Update the UUID when ID found.
> > +		 */
> > +		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
> > +			desc_found = 0;
> > +
> > +			/*
> > +			 * search the current ID in the cached partitions
> > +			 */
> > +			for (cached_desc_idx = 0;
> > +			     cached_desc_idx < ffa_priv_data->partitions.count;
> > +			     cached_desc_idx++) {
> > +				/*
> > +				 * save the UUID
> > +				 */
> > +				if (ffa_priv_data->partitions.descs[cached_desc_idx].info.id ==
> > +				    parts_info[rx_desc_idx].id) {
> > +					ffa_priv_data->partitions.descs[cached_desc_idx].sp_uuid =
> > +						*part_uuid;
> > +
> > +					desc_found = 1;
> > +					break;
> > +				}
> > +			}
> > +
> > +			if (!desc_found)
> > +				return -ENODATA;
> > +		}
> > +	}
> > +
> > +	return  0;
> > +}
> > +
> > +/**
> > + * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET and saves partitions data
> > + *
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + * @pcount: Pointer to the number of partitions variable filled when querying
> > + *
> > + * This function executes the FFA_PARTITION_INFO_GET
> > + * to query the partitions data. Then, it calls ffa_read_partitions_info
> > + * to save the data in the private data structure.
> > + *
> > + * After reading the data the RX buffer is released using ffa_release_rx_buffer
> > + *
> > + * Return:
> > + *
> > + * When part_uuid is NULL, all partitions data are retrieved from secure world
> > + * When part_uuid is non NULL, data for partitions matching the given UUID are
> > + * retrieved and the number of partitions is returned
> > + * 0 is returned on success. Otherwise, failure
> > + */
> > +static int ffa_query_partitions_info(struct ffa_partition_uuid *part_uuid,
> > +				     u32 *pcount)
> > +{
> > +	struct ffa_partition_uuid query_uuid = {0};
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +
> > +	/*
> > +	 * If a UUID is specified. Information for one or more
> > +	 * partitions in the system is queried. Otherwise, information
> > +	 * for all installed partitions is queried
> > +	 */
> > +
> > +	if (part_uuid) {
> > +		if (!pcount)
> > +			return -EINVAL;
> > +
> > +		query_uuid = *part_uuid;
> > +	} else if (pcount) {
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
> > +			.a1 = query_uuid.a1,
> > +			.a2 = query_uuid.a2,
> > +			.a3 = query_uuid.a3,
> > +			.a4 = query_uuid.a4,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		int ret;
> > +
> > +		/*
> > +		 * res.a2 contains the count of partition information descriptors
> > +		 * populated in the RX buffer
> > +		 */
> > +		if (res.a2) {
> > +			ret = ffa_read_partitions_info((u32)res.a2, part_uuid);
> > +			if (ret) {
> > +				ffa_err("failed to read partition(s) data , error (%d)", ret);
> > +				ffa_release_rx_buffer();
> > +				return -EINVAL;
> > +			}
> > +		}
> > +
> > +		/*
> > +		 * return the SP count (when querying using a UUID)
> > +		 */
> > +		if (pcount)
> > +			*pcount = (u32)res.a2;
> > +
> > +		/*
> > +		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
> > +		 * is assigned to the consumer (u-boot). So, we need to give
> > +		 * the ownership back to the SPM or hypervisor
> > +		 */
> > +		ret = ffa_release_rx_buffer();
> > +
> > +		return ret;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
> > +
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
> > + *
> > + * The passed arguments:
> > + * Mode 1: When getting from the driver the number of
> > + *	secure partitions:
> > + *	@uuid_str: pointer to the UUID string
> > + *	@parts_size: pointer to the variable that contains the number of partitions
> > + *			 The variable will be set by the driver
> > + *	@buffer: NULL
> > + *
> > + * Mode 2: When requesting the driver to return the
> > + *	partitions information:
> > + *	@uuid_str: pointer to the UUID string
> > + *	@parts_size: pointer to the size of the SPs information buffer in bytes
> > + *	@buffer: pointer to SPs information buffer
> > + *		(allocated by the client).
> > + *		The buffer will be filled by the driver
> > + *
> > + * This function queries the secure partition data from
> > + * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
> > + * FF-A function to query the partition information from secure world.
> > + *
> > + * A client of the FF-A driver should know the UUID of the service it wants to
> > + * access. It should use the UUID to request the FF-A driver to provide the
> > + * partition(s) information of the service. The FF-A driver uses
> > + * PARTITION_INFO_GET to obtain this information. This is implemented through
> > + * ffa_get_partitions_info function.
> > + * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
> > + * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
> > + * They are not saved (already done). We only update the UUID in the cached area.
> > + * This assumes that partitions data does not change in the secure world.
> > + * Otherwise u-boot will have an outdated partition data. The benefit of caching
> > + * the information in the FF-A driver is to accommodate discovery after
> > + * ExitBootServices().
> > + *
> > + * When invoked through a client request, ffa_get_partitions_info should be
> > + * called twice. First call is to get from the driver the number of secure
> > + * partitions (SPs) associated to a particular UUID.
> > + * Then, the caller (client) allocates the buffer to host the SPs data and
> > + * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
> > + * buffer.
> > + *
> > + * To achieve the mechanism described above, ffa_get_partitions_info uses the
> > + * following functions:
> > + *		ffa_read_partitions_info
> > + *		ffa_query_partitions_info
> > + *
> > + * Return:
> > + *
> > + * @parts_size: When pointing to the number of partitions variable, the number is
> > + * set by the driver.
> > + * When pointing to the partitions information buffer size, the buffer will be
> > + * filled by the driver.
> 
> This is confusing, it's better if you use the same unit all the time.
> Since you below require the size to be an even multiple of sizeof(struct
> ffa_partition_info) you should perhaps use that unit.

Addressed in v8 patchset.

> 
> > + *
> > + * On success 0 is returned. Otherwise, failure
> > + */
> > +static int ffa_get_partitions_info(const char *uuid_str,
> > +				   u32 *parts_size, struct ffa_partition_info *buffer)
> > +{
> > +	/*
> > +	 * fill_data:
> > +	 * 0: return the SP count
> > +	 * 1: fill SP data and return it to the caller
> > +	 * -1: undefined mode
> > +	 */
> > +	int fill_data = -1;
> 
> In the code below this is treated as a bool, it's never tested for -1,
> so you could as well make this a bool.

Addressed in v8 patchset.

> 
> > +	u32 desc_idx, client_desc_idx;
> > +	struct ffa_partition_uuid part_uuid = {0};
> > +	u32 client_desc_max_cnt;
> > +	u32 parts_found = 0;
> > +
> > +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs) {
> > +		ffa_err("no partition installed");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!uuid_str) {
> > +		ffa_err("no UUID provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!parts_size) {
> > +		ffa_err("no size/count provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
> > +		ffa_err("invalid UUID");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!buffer) {
> > +		/* Mode 1: getting the number of secure partitions */
> > +
> > +		fill_data = 0;
> > +
> > +		ffa_info("Preparing for checking partitions count");
> > +
> > +	} else if ((*parts_size >= sizeof(struct ffa_partition_info)) &&
> > +		   !(*parts_size % sizeof(struct ffa_partition_info))) {
> > +		/* Mode 2: retrieving the partitions information */
> > +
> > +		fill_data = 1;
> > +
> > +		client_desc_idx = 0;
> > +
> > +		/*
> > +		 * number of empty descriptors preallocated by the caller
> > +		 */
> > +		client_desc_max_cnt = *parts_size / sizeof(struct ffa_partition_info);
> > +
> > +		ffa_info("Preparing for filling partitions info");
> > +
> > +	} else {
> > +		ffa_err("invalid function arguments provided");
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_info("Searching partitions using the provided UUID");
> > +
> > +	/*
> > +	 * search in the cached partitions
> > +	 */
> > +	for (desc_idx = 0;
> > +	     desc_idx < ffa_priv_data->partitions.count;
> > +	     desc_idx++) {
> > +		if (ffa_uuid_are_identical(&ffa_priv_data->partitions.descs[desc_idx].sp_uuid,
> > +					   &part_uuid)) {
> > +			ffa_info("Partition ID %x matches the provided UUID",
> > +				 ffa_priv_data->partitions.descs[desc_idx].info.id);
> > +
> > +			parts_found++;
> > +
> > +			if (fill_data) {
> > +				/*
> > +				 * trying to fill the partition info in the input buffer
> > +				 */
> > +
> > +				if (client_desc_idx < client_desc_max_cnt) {
> > +					buffer[client_desc_idx++] =
> > +						ffa_priv_data->partitions.descs[desc_idx].info;
> > +					continue;
> > +				}
> > +
> > +				ffa_err("failed to fill the current descriptor client buffer full");
> > +				return -ENOBUFS;
> > +			}
> > +		}
> > +	}
> > +
> > +	if (!parts_found) {
> 
> By asking for a UUID never found ffa_query_partitions_info() will be
> called again, even if the rx/tx buffers needed are not available any
> longer. Since you populate the cache in ffa_probe() below, perhaps it
> would be better to only rely on the cache after that point.
> 
> > +		int ret;
> > +
> > +		ffa_info("No partition found. Querying framework ...");
> > +
> > +		ret = ffa_query_partitions_info(&part_uuid, &parts_found);
> > +
> > +		if (ret == 0) {
> > +			if (!fill_data) {
> > +				*parts_size = parts_found;
> > +
> > +				ffa_info("Number of partition(s) found matching the UUID: %d",
> > +					 parts_found);
> > +			} else {
> > +				/*
> > +				 * If SPs data detected, they are already in the private data
> > +				 * structure, retry searching SP data again to return them
> > +				 *  to the caller
> > +				 */
> > +				if (parts_found)
> > +					ret = ffa_get_partitions_info(uuid_str, parts_size, buffer);
> > +				else
> > +					ret = -ENODATA;
> > +			}
> > +		}
> > +
> > +		return ret;
> > +	}
> > +
> > +	/* partition(s) found */
> > +	if (!fill_data)
> > +		*parts_size = parts_found;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_cache_partitions_info - Queries and saves all secure partitions data
> > + *
> > + * This function invokes FFA_PARTITION_INFO_GET FF-A
> > + * function to query from secure world all partitions information.
> > + *
> > + * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
> > + * All installed partitions information are returned. We cache them in the
> > + * resident private data structure and we keep the UUID field empty
> > + * (in FF-A 1.0 UUID is not provided by the partition descriptor)
> > + *
> > + * This function is called at the device probing level.
> > + * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_cache_partitions_info(void)
> > +{
> > +	return ffa_query_partitions_info(NULL, NULL);
> > +}
> > +
> > +/**
> > + * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> > + * @dst_part_id: destination partition ID
> > + * @msg: pointer to the message data preallocated by the client (in/out)
> > + * @is_smc64: select 64-bit or 32-bit FF-A ABI
> > + *
> > + * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * FF-A functions.
> > + *
> > + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> > + * The response from the secure partition is handled by reading the
> > + * FFA_MSG_SEND_DIRECT_RESP arguments.
> > + *
> > + * The maximum size of the data that can be exchanged is 40 bytes which is
> > + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> > + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg, bool is_smc64)
> > +{
> > +	ffa_value_t res = {0};
> > +	int ffa_errno;
> > +	u64 req_mode, resp_mode;
> > +
> > +	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
> > +		return -EINVAL;
> > +
> > +	/* No partition installed */
> > +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
> > +		return -ENODEV;
> 
> This check isn't needed. What if the partition ID is known by other
> means?
> 
> > +
> > +	if (is_smc64) {
> > +		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
> > +		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
> > +	} else {
> > +		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
> > +		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
> > +	}
> > +
> > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = req_mode,
> > +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
> > +				PREP_PART_ENDPOINT_ID(dst_part_id),
> > +			.a2 = 0,
> > +			.a3 = msg->data0,
> > +			.a4 = msg->data1,
> > +			.a5 = msg->data2,
> > +			.a6 = msg->data3,
> > +			.a7 = msg->data4,
> > +			}, &res);
> > +
> > +	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
> > +		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +			.a0 = FFA_SMC_32(FFA_RUN),
> > +			.a1 = res.a1,
> > +			}, &res);
> > +
> > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > +		/* Message sent with no response */
> > +		return 0;
> > +	}
> > +
> > +	if (res.a0 == resp_mode) {
> > +		/*
> > +		 * Message sent with response
> > +		 * extract the return data
> > +		 */
> > +		msg->data0 = res.a3;
> > +		msg->data1 = res.a4;
> > +		msg->data2 = res.a5;
> > +		msg->data3 = res.a6;
> > +		msg->data4 = res.a7;
> > +
> > +		return 0;
> > +	}
> > +
> > +	ffa_errno = res.a2;
> > +	return ffa_to_std_errno(ffa_errno);
> > +}
> > +
> > +/**
> > + * __arm_ffa_fn_smc - 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 low level SMC assembly function
> > + *
> > + * Return: void
> > + */
> > +void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
> > +{
> > +	arm_smccc_1_2_smc(&args, res);
> > +}
> > +
> > +/**
> > + * ffa_set_smc_conduit - Set the SMC conduit
> > + *
> > + * This function selects the SMC conduit by setting the driver invoke function
> > + * to SMC assembly function
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_set_smc_conduit(void)
> > +{
> > +	ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc;
> > +
> > +	if (!ffa_priv_data->invoke_ffa_fn) {
> > +		ffa_err("failure to set the invoke function");
> > +		return -EINVAL;
> > +	}
> > +
> > +	ffa_info("Conduit is SMC");
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_set_bus_ops - Set the bus driver operations
> > + *
> > + * Setting the driver callbacks.
> > + *
> > + */
> > +static void ffa_set_bus_ops(void)
> > +{
> > +	ffa_priv_data->ffa_ops.partition_info_get = ffa_get_partitions_info;
> > +	ffa_priv_data->ffa_ops.sync_send_receive = ffa_msg_send_direct_req;
> > +	ffa_priv_data->ffa_ops.rxtx_unmap = ffa_unmap_rxtx_buffers;
> > +}
> > +
> > +/**
> > + * ffa_alloc_prvdata - allocate the driver main data structure and sets the device
> > + * @dev:	the arm_ffa device
> > + *
> > + * This function creates the main data structure embedding all the driver data.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_alloc_prvdata(struct udevice *dev)
> > +{
> > +	if (!dev) {
> > +		ffa_err("no udevice found");
> > +		return -ENODEV;
> > +	}
> > +
> > +	/* The device is registered with the DM. Let's create the driver main data structure*/
> > +
> > +	ffa_priv_data = devm_kmalloc(dev, sizeof(struct ffa_prvdata), __GFP_ZERO);
> > +	if (!ffa_priv_data) {
> > +		ffa_err("can not allocate the driver main data structure");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	ffa_priv_data->dev = dev;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_probe - The driver probe function
> > + * @dev:	the arm_ffa device
> > + *
> > + * Probing is done at boot time and triggered by the uclass device discovery.
> > + * At probe level the following actions are done:
> > + *	- setting the conduit
> > + *	- querying the FF-A framework version
> > + *	- querying from secure world the u-boot endpoint ID
> > + *	- querying from secure world the supported features of FFA_RXTX_MAP
> > + *	- mapping the RX/TX buffers
> > + *	- querying from secure world all the partitions information
> > + *
> > + * All data queried from secure world is saved in the resident private data structure.
> > + *
> > + * The probe will fail if either FF-A framework is not detected or the
> > + * FF-A requests are not behaving correctly. This ensures that the
> > + * driver is not installed and its operations are not exported to the clients.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_probe(struct udevice *dev)
> > +{
> > +	int ret;
> > +
> > +	ret = ffa_alloc_prvdata(dev);
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ffa_set_bus_ops();
> > +
> > +	ret = ffa_set_smc_conduit();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_version();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_endpoint_id();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_get_rxtx_map_features();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_map_rxtx_buffers();
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	ret = ffa_cache_partitions_info();
> > +	if (ret != 0) {
> > +		ffa_free_rxtx_buffers();
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_remove - The driver remove function
> > + * @dev:	the arm_ffa device
> > + * When the device is about to be removed ,  unmap the RX/TX buffers and free the memory
> > + * Return:
> > + *
> > + * 0 on success.
> > + */
> > +static int ffa_remove(struct udevice *dev)
> > +{
> > +	ffa_info("removing the device");
> > +
> > +	ffa_unmap_rxtx_buffers();
> > +
> > +	if (ffa_priv_data->pair.rxbuf || ffa_priv_data->pair.txbuf)
> > +		ffa_free_rxtx_buffers();
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_unbind - The driver unbind function
> > + * @dev:	the arm_ffa device
> > + * After the device is removed and memory freed the device is unbound
> > + * Return:
> > + *
> > + * 0 on success.
> > + */
> > +static int ffa_unbind(struct udevice *dev)
> > +{
> > +	ffa_info("unbinding the device , private data already released");
> > +
> > +	ffa_priv_data = NULL;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_bus_ops_get - bus driver operations getter
> > + *
> > + * Return:
> > + * This function returns a pointer to the driver operations structure
> > + */
> > +const struct ffa_bus_ops *ffa_bus_ops_get(void)
> > +{
> > +	return &ffa_priv_data->ffa_ops;
> > +}
> > +
> > +/**
> > + * ffa_bus_prvdata_get - bus driver private data getter
> > + *
> > + * Return:
> > + * This function returns a pointer to the main private data structure
> > + */
> > +struct ffa_prvdata **ffa_bus_prvdata_get(void)
> 
> Why a pointer to a pointer, isn't "struct ffa_prvdata *" enough?
> 
> > +{
> > +	return &ffa_priv_data;
> > +}
> > +
> > +/**
> > + * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
> > + *
> > + * 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 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.
> > + * All FF-A clients should use the arm_ffa device to use the FF-A transport.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_bus_discover(void)
> > +{
> > +	int ret = 0;
> > +
> > +	if (!ffa_priv_data)
> > +		ret = ffa_device_get();
> > +
> > +	return ret;
> > +}
> > +
> > +/**
> > + * Declaring the arm_ffa driver under UCLASS_FFA
> > + */
> > +
> > +U_BOOT_DRIVER(arm_ffa) = {
> > +	.name		= FFA_DRV_NAME,
> > +	.id		= UCLASS_FFA,
> > +	.probe		= ffa_probe,
> > +	.remove		= ffa_remove,
> > +	.unbind		= ffa_unbind,
> > +};
> > diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> > new file mode 100644
> > index 0000000000..b0c8a18926
> > --- /dev/null
> > +++ b/include/arm_ffa.h
> > @@ -0,0 +1,93 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_H
> > +#define __ARM_FFA_H
> > +
> > +#include <linux/printk.h>
> > +
> > +/*
> > + * This header is public. It can be used by clients to access
> > + * data structures and definitions they need
> > + */
> > +
> > +/*
> > + * Macros for displaying logs
> > + */
> > +
> > +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +
> > +/*
> > + * struct ffa_partition_info - Partition information descriptor
> > + * @id:	Partition ID
> > + * @exec_ctxt:	Execution context count
> > + * @properties:	Partition properties
> > + *
> > + * Data structure containing information about partitions instantiated in the system
> > + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> > + */
> > +struct  __packed ffa_partition_info {
> > +	u16 id;
> > +	u16 exec_ctxt;
> > +/* partition supports receipt of direct requests */
> > +#define FFA_PARTITION_DIRECT_RECV	BIT(0)
> > +/* partition can send direct requests. */
> > +#define FFA_PARTITION_DIRECT_SEND	BIT(1)
> > +/* partition can send and receive indirect messages. */
> > +#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
> > +	u32 properties;
> > +};
> 
> Perhaps this has been discussed before. Why is this packed? Is it to allow
> unaligned access or to be sure that there is not implicitly added padding?
> The Linux kernel does seem to need it.
> 
> > +
> > +/*
> > + * struct ffa_send_direct_data - Data structure hosting the data
> > + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * @data0-4:	Data read/written from/to x3-x7 registers
> > + *
> > + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> > + * or read from FFA_MSG_SEND_DIRECT_RESP
> > + */
> > +
> > +/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
> > +struct __packed ffa_send_direct_data {
> > +	unsigned long data0; /* w3/x3 */
> > +	unsigned long data1; /* w4/x4 */
> > +	unsigned long data2; /* w5/x5 */
> > +	unsigned long data3; /* w6/x6 */
> > +	unsigned long data4; /* w7/x7 */
> > +};
> 
> Why is this __packed? It seems unnecessary.
> 
> Cheers,
> Jens
> 
> > +
> > +/**
> > + * struct ffa_bus_ops - The driver operations structure
> > + * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
> > + * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
> > + * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
> > + *
> > + * The data structure providing all the operations supported by the driver.
> > + * This structure is EFI runtime resident.
> > + */
> > +struct ffa_bus_ops {
> > +	int (*partition_info_get)(const char *uuid_str,
> > +				  u32 *parts_size, struct ffa_partition_info *buffer);
> > +	int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg, bool is_smc64);
> > +	int (*rxtx_unmap)(void);
> > +};
> > +
> > +/**
> > + * The device driver and the Uclass driver public functions
> > + */
> > +
> > +/**
> > + * ffa_bus_ops_get - driver operations getter
> > + */
> > +const struct ffa_bus_ops *ffa_bus_ops_get(void);
> > +
> > +/**
> > + * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
> > + */
> > +int ffa_bus_discover(void);
> > +
> > +#endif
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index 4b2c323452..fb59d4f356 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -4,6 +4,9 @@
> >   *
> >   * (C) Copyright 2012
> >   * Pavel Herrmann <morpheus.ibis@gmail.com>
> > + *
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  
> >  #ifndef _DM_UCLASS_ID_H
> > @@ -55,6 +58,7 @@ enum uclass_id {
> >  	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
> >  	UCLASS_ETH,		/* Ethernet device */
> >  	UCLASS_ETH_PHY,		/* Ethernet PHY device */
> > +	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
> >  	UCLASS_FIRMWARE,	/* Firmware */
> >  	UCLASS_FPGA,		/* FPGA device */
> >  	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
> > -- 
> > 2.17.1
> > 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v7 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-15 10:32                                             ` Jens Wiklander
@ 2022-11-22 13:33                                               ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:33 UTC (permalink / raw)
  To: Jens Wiklander; +Cc: u-boot, nd

On Tue, Nov 15, 2022 at 11:32:49AM +0100, Jens Wiklander wrote:
> On Fri, Nov 11, 2022 at 02:36:11PM +0000, Abdellatif El Khlifi wrote:
> > On Wed, Nov 09, 2022 at 12:51:26PM +0100, Jens Wiklander wrote:
> > > On Mon, Nov 07, 2022 at 07:20:48PM +0000, Abdellatif El Khlifi wrote:
> [snip]
> > > > +/**
> > > > + * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> > > > + * @dst_part_id: destination partition ID
> > > > + * @msg: pointer to the message data preallocated by the client (in/out)
> > > > + * @is_smc64: select 64-bit or 32-bit FF-A ABI
> > > > + *
> > > > + * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > > > + * FF-A functions.
> > > > + *
> > > > + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> > > > + * The response from the secure partition is handled by reading the
> > > > + * FFA_MSG_SEND_DIRECT_RESP arguments.
> > > > + *
> > > > + * The maximum size of the data that can be exchanged is 40 bytes which is
> > > > + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> > > > + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > > > + *
> > > > + * Return:
> > > > + *
> > > > + * 0 on success. Otherwise, failure
> > > > + */
> > > > +static int ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_send_direct_data *msg, bool is_smc64)
> > > > +{
> > > > +	ffa_value_t res = {0};
> > > > +	int ffa_errno;
> > > > +	u64 req_mode, resp_mode;
> > > > +
> > > > +	if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
> > > > +		return -EINVAL;
> > > > +
> > > > +	/* No partition installed */
> > > > +	if (!ffa_priv_data->partitions.count || !ffa_priv_data->partitions.descs)
> > > > +		return -ENODEV;
> > > 
> > > This check isn't needed. What if the partition ID is known by other
> > > means?
> > 
> > I'm happy to remove this check. I'd like to add a comment explaining
> > what the other means are. Could you please explain what are they ?
> 
> In some systems perhaps you have well known partition ids reserved for
> certain services.

I double checked with Achin about this. 

FFA_PARTITION_INFO_GET provides the partitions information for all 
partitions including the reserved ones. The driver will cache the
information of all the partitions. Not finding any partition cached
before a direct request means: there is no partition in the system.
I think we need to keep the check.

> 
> > 
> > > 
> > > > +
> > > > +	if (is_smc64) {
> > > > +		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
> > > > +		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
> > > > +	} else {
> > > > +		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
> > > > +		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
> > > > +	}
> > > > +
> > > > +	ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > > > +			.a0 = req_mode,
> > > > +			.a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data->id) |
> > > > +				PREP_PART_ENDPOINT_ID(dst_part_id),
> > > > +			.a2 = 0,
> > > > +			.a3 = msg->data0,
> > > > +			.a4 = msg->data1,
> > > > +			.a5 = msg->data2,
> > > > +			.a6 = msg->data3,
> > > > +			.a7 = msg->data4,
> > > > +			}, &res);
> > > > +
> > > > +	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
> > > > +		ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > > > +			.a0 = FFA_SMC_32(FFA_RUN),
> > > > +			.a1 = res.a1,
> > > > +			}, &res);
> > > > +
> > > > +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> > > > +		/* Message sent with no response */
> > > > +		return 0;
> > > > +	}
> > > > +
> > > > +	if (res.a0 == resp_mode) {
> > > > +		/*
> > > > +		 * Message sent with response
> > > > +		 * extract the return data
> > > > +		 */
> > > > +		msg->data0 = res.a3;
> > > > +		msg->data1 = res.a4;
> > > > +		msg->data2 = res.a5;
> > > > +		msg->data3 = res.a6;
> > > > +		msg->data4 = res.a7;
> > > > +
> > > > +		return 0;
> > > > +	}
> > > > +
> > > > +	ffa_errno = res.a2;
> > > > +	return ffa_to_std_errno(ffa_errno);
> > > > +}
> > > > +
> 
> [snip]
> 
> > > > +/**
> > > > + * ffa_bus_prvdata_get - bus driver private data getter
> > > > + *
> > > > + * Return:
> > > > + * This function returns a pointer to the main private data structure
> > > > + */
> > > > +struct ffa_prvdata **ffa_bus_prvdata_get(void)
> > > 
> > > Why a pointer to a pointer, isn't "struct ffa_prvdata *" enough?
> > 
> > Because ffa_priv_data is a pointer. ffa_bus_prvdata_get() returns an
> > address of a pointer so the returned type should be struct ffa_prvdata
> > **
> > 
> > Otherwise, a compiler warning:
> > 
> > drivers/firmware/arm-ffa/core.c: In function ‘ffa_bus_prvdata_get’:
> > drivers/firmware/arm-ffa/core.c:1278:9: warning: return from incompatible pointer type [-Wincompatible-pointer-types]
> >   return &ffa_priv_data;
> >          ^~~~~~~~~~~~~~
> 
> Why not return ffa_priv_data instead?

Thanks, addressed in v8 patchset.

> 
> > 
> > > 
> > > > +{
> > > > +	return &ffa_priv_data;
> > > > +}
> 
> [snip]
> 
>  > > +++ b/include/arm_ffa.h
> > > > @@ -0,0 +1,93 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > > +/*
> > > > + * (C) Copyright 2022 ARM Limited
> > > > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > + */
> > > > +
> > > > +#ifndef __ARM_FFA_H
> > > > +#define __ARM_FFA_H
> > > > +
> > > > +#include <linux/printk.h>
> > > > +
> > > > +/*
> > > > + * This header is public. It can be used by clients to access
> > > > + * data structures and definitions they need
> > > > + */
> > > > +
> > > > +/*
> > > > + * Macros for displaying logs
> > > > + */
> > > > +
> > > > +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> > > > +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> > > > +
> > > > +/*
> > > > + * struct ffa_partition_info - Partition information descriptor
> > > > + * @id:	Partition ID
> > > > + * @exec_ctxt:	Execution context count
> > > > + * @properties:	Partition properties
> > > > + *
> > > > + * Data structure containing information about partitions instantiated in the system
> > > > + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> > > > + */
> > > > +struct  __packed ffa_partition_info {
> > > > +	u16 id;
> > > > +	u16 exec_ctxt;
> > > > +/* partition supports receipt of direct requests */
> > > > +#define FFA_PARTITION_DIRECT_RECV	BIT(0)
> > > > +/* partition can send direct requests. */
> > > > +#define FFA_PARTITION_DIRECT_SEND	BIT(1)
> > > > +/* partition can send and receive indirect messages. */
> > > > +#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
> > > > +	u32 properties;
> > > > +};
> > > 
> > > Perhaps this has been discussed before. Why is this packed? Is it to allow
> > > unaligned access or to be sure that there is not implicitly added padding?
> > > The Linux kernel does seem to need it.
> > 
> > When not using __packed the compiler will add paddings.
> > ffa_partition_info structure is used for reading SP information
> > from the secure world.
> > 
> > The issue arises when the non secure world and the secure world
> > have different architectures (Aarch64 vs Aarch32) or different
> > endianess. In these cases, the data will be corrupted.
> > 
> > I think we need to use __packed for all the comms structures.
> > 
> > I'm aware ffa_partition_info in the kernel is not packed. I'm happy
> > to remove __packed from here to align it with Linux.
> > 
> > But please share your thoughts about the padding issues when
> > working with different architecures/endianess.
> 
> __packed doesn't help with endianess, besides if I remember correctly
> these are always expected to be little endian. But I guess that could be
> a problem for another day.
> 
> I believe the layout of these structs are designed in a way that a
> reasonable compiler wouldn't add padding on AArch32 or AArch64. Note
> that packed does more than just force generation of inefficient code on
> Arm (unaligned access), it also makes it invalid to take the address of
> a member inside such a struct.

Packing removed from ffa_partition_info and ffa_send_direct_data structures
in v8 patchset.

> 
> Cheers,
> Jens

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v7 09/10] arm_ffa: efi: introduce FF-A MM communication
  2022-11-15  9:03                                         ` Ilias Apalodimas
@ 2022-11-22 13:37                                           ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:37 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, nd

On Tue, Nov 15, 2022 at 11:03:51AM +0200, Ilias Apalodimas wrote:
> Hi Abdellatif
> 
> On Mon, Nov 07, 2022 at 07:20:54PM +0000, Abdellatif El Khlifi wrote:
> > Add MM communication support using FF-A transport
> > 
> > This feature allows accessing MM partitions services through
> > EFI MM communication protocol. MM partitions such as StandAlonneMM
> > or smm-gateway secure partitions which reside in secure world.
> > 
> > An MM shared buffer and a door bell event are used to exchange
> > the data.
> > 
> > The data is used by EFI services such as GetVariable()/SetVariable()
> > and copied from the communication buffer to the MM shared buffer.
> >  
> >  config EFI_MM_COMM_TEE
> > -	bool "UEFI variables storage service via OP-TEE"
> > -	depends on OPTEE
> > +	bool "UEFI variables storage service via the trusted world"
> > +	depends on OPTEE && ARM_FFA_TRANSPORT
> 
> This shouldn't rely on both.  It's either OP-TEE or FF-A

Thanks. Addressed in v8 patchset.

> 
> >  
> > +#if (IS_ENABLED(CONFIG_OPTEE))
> 
> This separation is a bit problematic.  A user can configure bot OP-TEE and
> FF-A. Those are not mutually exclusive,  but for the EFI
> variables case they are.  We need a better way to isolate the compilation
> choices.  Why don't we make ffa_bus_discover() return -1 if FF-A isn't
> compiled in?

I agree, this is addressed in v8 patchset.

> 
> >  /**
> >   * get_connection() - Retrieve OP-TEE session for a specific UUID.
> >   *
> > @@ -143,13 +176,229 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
> >  
> >  	return ret;
> >  }
> > +#endif
> > +
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +
> > +/**
> > + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> > + *
> > + * Notifies the MM partition in the trusted world that
> > + * data is available in the shared buffer.
> > + * This is a blocking call during which trusted world has exclusive access
> > + * to the MM shared buffer.
> > + *
> > + * Return:
> > + *
> > + * 0 on success
> > + */
> > +static int ffa_notify_mm_sp(void)
> > +{
> > +	struct ffa_send_direct_data msg = {0};
> > +	int ret;
> > +	int sp_event_ret = -1;
> > +
> > +	if (!ffa_bus_ops_get())
> > +		return -EINVAL;
> > +
> > +	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
> > +
> > +	ret = ffa_bus_ops_get()->sync_send_receive(mm_sp_id, &msg, 1);
> > +	if (ret != 0)
> > +		return ret;
> > +
> > +	sp_event_ret = msg.data0; /* x3 */
> > +
> > +	if (sp_event_ret == MM_SUCCESS)
> > +		return 0;
> > +
> > +	/*
> > +	 * Failure to notify the MM SP
> > +	 */
> > +
> > +	return -EACCES;
> > +}
> > +
> > +/**
> > + * ffa_discover_mm_sp_id() - Query the MM partition ID
> > + *
> > + * Use the FF-A driver to get the MM partition ID.
> > + * If multiple partitions are found, use the first one.
> > + * This is a boot time function.
> > + *
> > + * Return:
> > + *
> > + * 0 on success
> > + */
> > +static int ffa_discover_mm_sp_id(void)
> > +{
> > +	u32 count = 0, size = 0;
> > +	int ret;
> > +	struct ffa_partition_info *parts_info;
> > +
> > +	if (!ffa_bus_ops_get())
> > +		return -EINVAL;
> > +
> > +	/*
> > +	 * get from the driver the count of the SPs matching the UUID
> > +	 */
> > +	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &count, NULL);
> > +	if (ret != 0) {
> > +		log_err("EFI: Failure in querying partitions count (error code: %d)\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	if (!count) {
> > +		log_info("EFI: No MM partition found\n");
> > +		return ret;
> > +	}
> > +
> > +	/*
> > +	 * pre-allocate a buffer to be filled by the driver
> > +	 * with	 ffa_partition_info structs
> > +	 */
> > +
> > +	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
> > +
> > +	parts_info = calloc(count, sizeof(struct ffa_partition_info));
> 
> I prefer sizeof(*parts_info).  Same goes for all sizeof() calls.

Addressed in v8 patchset.

> 
> > +	if (!parts_info)
> > +		return -ENOMEM;
> > +
> > +	size = count * sizeof(struct ffa_partition_info);
> > +
> > +	/*
> > +	 * ask the driver to fill the
> > +	 * buffer with the SPs info
> > +	 */
> > +	ret = ffa_bus_ops_get()->partition_info_get(mm_sp_svc_uuid, &size, parts_info);
> > +	if (ret != 0) {
> 
> if (!ret)

Addressed in v8 patchset.

> 
>  
> [...]
> 
> Thanks
> /Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-18 20:50                                     ` Simon Glass
@ 2022-11-22 13:49                                       ` Abdellatif El Khlifi
  2022-11-22 22:24                                         ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-22 13:49 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, nd

On Fri, Nov 18, 2022 at 01:50:26PM -0700, Simon Glass wrote:
> Hi,
> 
> On Wed, 16 Nov 2022 at 06:03, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > On Tue, Nov 15, 2022 at 08:24:24AM -0700, Simon Glass wrote:
> > > Hi,
> > >
> > > On Mon, 1 Aug 2022 at 11:21, Abdellatif El Khlifi
> > > <abdellatif.elkhlifi@arm.com> wrote:
> > > >
> > > > Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
> > > >
> > > > The Firmware Framework for Arm A-profile processors (FF-A)
> > > > describes interfaces (ABIs) that standardize communication
> > > > between the Secure World and Normal World leveraging TrustZone
> > > > technology.
> > > >
> > > > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > > > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > > > querying the FF-A framework from the secure world.
> > > >
> > > > 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> > > > and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> > > >
> > > > In u-boot FF-A design, FF-A is considered as a discoverable bus.
> > > > The Secure World is considered as one entity to communicate with
> > > > using the FF-A bus. FF-A communication is handled by one device and
> > > > one instance (the bus). This FF-A driver takes care of all the
> > > > interactions between Normal world and Secure World.
> > > >
> > > > The driver exports its operations to be used by upper layers.
> > > >
> > > > Exported operations:
> > > >
> > > > - partition_info_get
> > > > - sync_send_receive
> > > > - rxtx_unmap
> > > >
> > > > This implementation provides an optional feature to copy the driver data
> > > > to EFI runtime area.
> > > >
> > > > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > Cc: Tom Rini <trini@konsulko.com>
> > > > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > > > Cc: Jens Wiklander <jens.wiklander@linaro.org>
> > > > ---
> > > >  MAINTAINERS                                |    6 +
> > > >  common/board_r.c                           |    7 +
> > > >  drivers/Kconfig                            |    2 +
> > > >  drivers/Makefile                           |    1 +
> > > >  drivers/arm-ffa/Kconfig                    |   33 +
> > > >  drivers/arm-ffa/Makefile                   |    7 +
> > > >  drivers/arm-ffa/arm-ffa-uclass.c           |   16 +
> > > >  drivers/arm-ffa/arm_ffa_prv.h              |  219 ++++
> > > >  drivers/arm-ffa/core.c                     | 1338 ++++++++++++++++++++
> > > >  drivers/arm-ffa/efi_ffa_runtime_data_mgr.c |   94 ++
> > > >  include/arm_ffa.h                          |  132 ++
> > > >  include/dm/uclass-id.h                     |    1 +
> > > >  include/uuid.h                             |    8 +
> > > >  lib/efi_loader/efi_boottime.c              |   17 +
> > > >  lib/uuid.c                                 |   65 +
> > > >  15 files changed, 1946 insertions(+)
> > > >  create mode 100644 drivers/arm-ffa/Kconfig
> > > >  create mode 100644 drivers/arm-ffa/Makefile
> > > >  create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
> > > >  create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
> > > >  create mode 100644 drivers/arm-ffa/core.c
> > > >  create mode 100644 drivers/arm-ffa/.c
> > > >  create mode 100644 include/arm_ffa.h
> > >
> > > Please add something to doc/ so people know what this is.
> > >
> > > Since you are adding a new uclass you need a sandbox driver and tests.
> > >
> > > The driver appears to have no operations, but there is a bus_ops. The
> > > ops should go in the driver, I suspect, and should pass the device as
> > > the first arg.
> > >
> > > Can FFA_ERR_STAT_SUCCESS be 0 so you don't have to sprinkle the code with it?
> > >
> > > Why is it using EFI things? Can this driver only be used with UEFI? I
> > > hope not, if it is an official way of updating firmware.
> > >
> > > Please don't add more things to board_r.c - we are trying to remove
> > > this init over time. If it is a device it should be probed as needed.
> > >
> > > Is there a device tree binding?
> > >
> > > Also should this go in drivers/misc instead of creating a whole new subdir?
> >
> > Hi Simon, thanks for reviewing.
> >
> > All the above comments have already been addressed in the new versions
> > of the patchset. Please refer to the latest version v7 [1].
> >
> > By the way I'd like to highlight the following:
> >
> > - The FF-A driver documentation is at doc/arch/arm64.ffa.rst, please
> >   refer to it since it provides helpful details about the FF-A support
> >   in U-Boot
> 
> OK
> 
> > - The patchset comes with Sandbox driver and tests [2]
> 
> OK I suppose I saw that previously and forgot.
> 
> > - The driver has operations defined in struct ffa_bus_ops (include/arm_ffa.h).
> >   ffa_bus_ops_get() gets the ops. All these are in the driver (drivers/firmware/arm-ffa/core.c)
> 
> Can you please push a tree somewhere so I can look?

OK, I'll share the link to a public branch so you can refer to once it's created.

> 
> > - The FF-A bus has only 1 device. No multiple instances. So passing the
> >   device doesn't make sense in our case
> 
> It must still pass the device.

I added this feature in patchset v8. Please refer to the latest patchset when reviewing [1].

[1]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/

> 
> > - FFA_ERR_STAT_SUCCESS has been removed and replaced with 0
> 
> OK
> 
> > - The driver is independent from EFI and can be compiled without EFI
> 
> Oh, so what is ffa_copy_runtime_data() for?

This has already been dropped in newer versions of the pachset. Could you please refer to the latest ? (v8)
> 
> > - FF-A bus discovery has been removed from the initcall level (board_r.c)
> 
> Good.
> 
> >   Discovery is done on demand. Clients can call ffa_bus_discover() when
> >   they want to use the FF-A bus. As an example of how clients initiate
> >   discovery please refer to the FF-A MM comms client [3].
> 
> Is there a command to do this?

If you mean whether there is a command to showcase this, yes.

I already created the armffa command as an example of how to use the FF-A bus
and how clients can discover it.

Please refer to this commit [1].

[1]: https://lore.kernel.org/all/20221122131751.22747-6-abdellatif.elkhlifi@arm.com/

> 
> > - As done in the Linux kernel, the FF-A bus doesn't have a device tree
> >   binding since there is no peripheral associated with FF-A. At the
> >   early stages of this patchset, we double checked with the device tree
> >   maintainer and the decision was no device tree for FF-A
> 
> Sorry, but you must add one.

We had a discussion on this on April 2022 with Rob Herring. We decided to do
the same as the FF-A kernel driver: no device tree, we perform a manual bus discovery.

Rob Herring stated the following:

- There is not a 'kernel device tree' and a 'u-boot device tree'. There is only 1
- The FFA DT binding was rejected in favor of making FFA discoverable.
   The FFA spec was amended to address that. DT is only for what we
   failed to make discoverable. For hardware, we're stuck with it. We
   shouldn't repeat that for software interfaces.

For more details please refer to [1].

[1]: https://lore.kernel.org/all/CAL_Jsq+dwHqwDdALTAwU-VYW2=2kYCyHpv7mUP0zR04CwH101Q@mail.gmail.com/

> 
> > - The links below are from the U-Boot mailing list mirror in lore.kernel.org
> 
> Regards,
> Simon
> 
> 
> >
> > Cheers.
> >
> > [1]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
> > [2]: https://lore.kernel.org/all/20221107192055.21669-7-abdellatif.elkhlifi@arm.com/
> >      https://lore.kernel.org/all/20221107192055.21669-8-abdellatif.elkhlifi@arm.com/
> >      https://lore.kernel.org/all/20221107192055.21669-9-abdellatif.elkhlifi@arm.com/
> > [3]: https://lore.kernel.org/all/20221107192055.21669-10-abdellatif.elkhlifi@arm.com/
> > >
> > > Regards,
> > > Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-22 13:49                                       ` Abdellatif El Khlifi
@ 2022-11-22 22:24                                         ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2022-11-22 22:24 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: u-boot, nd

Hi Abdellatif,

On Tue, 22 Nov 2022 at 06:50, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> On Fri, Nov 18, 2022 at 01:50:26PM -0700, Simon Glass wrote:
> > Hi,
> >
> > On Wed, 16 Nov 2022 at 06:03, Abdellatif El Khlifi
> > <abdellatif.elkhlifi@arm.com> wrote:
> > >
> > > On Tue, Nov 15, 2022 at 08:24:24AM -0700, Simon Glass wrote:
> > > > Hi,
> > > >
> > > > On Mon, 1 Aug 2022 at 11:21, Abdellatif El Khlifi
> > > > <abdellatif.elkhlifi@arm.com> wrote:
> > > > >
> > > > > Add the driver implementing Arm Firmware Framework for Armv8-A v1.0
> > > > >
> > > > > The Firmware Framework for Arm A-profile processors (FF-A)
> > > > > describes interfaces (ABIs) that standardize communication
> > > > > between the Secure World and Normal World leveraging TrustZone
> > > > > technology.
> > > > >
> > > > > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > > > > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > > > > querying the FF-A framework from the secure world.
> > > > >
> > > > > 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP
> > > > > and FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> > > > >
> > > > > In u-boot FF-A design, FF-A is considered as a discoverable bus.
> > > > > The Secure World is considered as one entity to communicate with
> > > > > using the FF-A bus. FF-A communication is handled by one device and
> > > > > one instance (the bus). This FF-A driver takes care of all the
> > > > > interactions between Normal world and Secure World.
> > > > >
> > > > > The driver exports its operations to be used by upper layers.
> > > > >
> > > > > Exported operations:
> > > > >
> > > > > - partition_info_get
> > > > > - sync_send_receive
> > > > > - rxtx_unmap
> > > > >
> > > > > This implementation provides an optional feature to copy the driver data
> > > > > to EFI runtime area.
> > > > >
> > > > > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > > Cc: Tom Rini <trini@konsulko.com>
> > > > > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > > > > Cc: Jens Wiklander <jens.wiklander@linaro.org>
> > > > > ---
> > > > >  MAINTAINERS                                |    6 +
> > > > >  common/board_r.c                           |    7 +
> > > > >  drivers/Kconfig                            |    2 +
> > > > >  drivers/Makefile                           |    1 +
> > > > >  drivers/arm-ffa/Kconfig                    |   33 +
> > > > >  drivers/arm-ffa/Makefile                   |    7 +
> > > > >  drivers/arm-ffa/arm-ffa-uclass.c           |   16 +
> > > > >  drivers/arm-ffa/arm_ffa_prv.h              |  219 ++++
> > > > >  drivers/arm-ffa/core.c                     | 1338 ++++++++++++++++++++
> > > > >  drivers/arm-ffa/efi_ffa_runtime_data_mgr.c |   94 ++
> > > > >  include/arm_ffa.h                          |  132 ++
> > > > >  include/dm/uclass-id.h                     |    1 +
> > > > >  include/uuid.h                             |    8 +
> > > > >  lib/efi_loader/efi_boottime.c              |   17 +
> > > > >  lib/uuid.c                                 |   65 +
> > > > >  15 files changed, 1946 insertions(+)
> > > > >  create mode 100644 drivers/arm-ffa/Kconfig
> > > > >  create mode 100644 drivers/arm-ffa/Makefile
> > > > >  create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
> > > > >  create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
> > > > >  create mode 100644 drivers/arm-ffa/core.c
> > > > >  create mode 100644 drivers/arm-ffa/.c
> > > > >  create mode 100644 include/arm_ffa.h
> > > >

[..]

> > OK
> >
> > > - The driver is independent from EFI and can be compiled without EFI
> >
> > Oh, so what is ffa_copy_runtime_data() for?
>
> This has already been dropped in newer versions of the pachset. Could you please refer to the latest ? (v8)

OK I will take a look at the latest.

> >
> > > - FF-A bus discovery has been removed from the initcall level (board_r.c)
> >
> > Good.
> >
> > >   Discovery is done on demand. Clients can call ffa_bus_discover() when
> > >   they want to use the FF-A bus. As an example of how clients initiate
> > >   discovery please refer to the FF-A MM comms client [3].
> >
> > Is there a command to do this?
>
> If you mean whether there is a command to showcase this, yes.
>
> I already created the armffa command as an example of how to use the FF-A bus
> and how clients can discover it.
>
> Please refer to this commit [1].
>
> [1]: https://lore.kernel.org/all/20221122131751.22747-6-abdellatif.elkhlifi@arm.com/
>
> >
> > > - As done in the Linux kernel, the FF-A bus doesn't have a device tree
> > >   binding since there is no peripheral associated with FF-A. At the
> > >   early stages of this patchset, we double checked with the device tree
> > >   maintainer and the decision was no device tree for FF-A
> >
> > Sorry, but you must add one.
>
> We had a discussion on this on April 2022 with Rob Herring. We decided to do
> the same as the FF-A kernel driver: no device tree, we perform a manual bus discovery.
>
> Rob Herring stated the following:
>
> - There is not a 'kernel device tree' and a 'u-boot device tree'. There is only 1
> - The FFA DT binding was rejected in favor of making FFA discoverable.
>    The FFA spec was amended to address that. DT is only for what we
>    failed to make discoverable. For hardware, we're stuck with it. We
>    shouldn't repeat that for software interfaces.

OK. Rob and I will need to discuss this, but in the meantime, we
should hold off on this series.

I am certainly not saying there should be two device trees. But there
needs to be a binding for this thing.

>
> For more details please refer to [1].
>
> [1]: https://lore.kernel.org/all/CAL_Jsq+dwHqwDdALTAwU-VYW2=2kYCyHpv7mUP0zR04CwH101Q@mail.gmail.com/
>
> >
> > > - The links below are from the U-Boot mailing list mirror in lore.kernel.org
> >
> > Regards,
> > Simon
> >
> >
> > >
> > > Cheers.
> > >
> > > [1]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
> > > [2]: https://lore.kernel.org/all/20221107192055.21669-7-abdellatif.elkhlifi@arm.com/
> > >      https://lore.kernel.org/all/20221107192055.21669-8-abdellatif.elkhlifi@arm.com/
> > >      https://lore.kernel.org/all/20221107192055.21669-9-abdellatif.elkhlifi@arm.com/
> > > [3]: https://lore.kernel.org/all/20221107192055.21669-10-abdellatif.elkhlifi@arm.com/
> > > >
> > > > Regards,
> > > > Simon

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2022-11-22 13:17                                         ` [PATCH v8 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2022-11-23  2:09                                           ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2022-11-23  2:09 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	trini, u-boot, vishnu.banavath, xueliang.zhong

Hi Abdellatif,

On Tue, 22 Nov 2022 at 06:18, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> convert UUID string to little endian binary data
>
> 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>
>
> ---
>
> Changelog:
> ===============
>
> v8:
>
> * use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms
>
> v7:
>
> * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> * make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
>   by using same APIs
>
> v4:
>
> * rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
>   a standalone commit (the current)
>
> v3:
>
> * introduce ffa_uuid_str_to_bin (provided by
>   arm_ffa: introduce Arm FF-A low-level driver)
>
> include/uuid.h |  8 ++++++++
>  lib/uuid.c     | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 54 insertions(+)

Can you please add a full function comment in the header and also a
test, perhaps in test/lib/uuid.c ?

REgards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-22 13:17                                         ` [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
@ 2022-11-23  2:09                                           ` Simon Glass
  2022-11-24 13:21                                             ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2022-11-23  2:09 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	trini, u-boot, vishnu.banavath, xueliang.zhong

 should be called 'priov' and should beHi Abdellatif,

On Tue, 22 Nov 2022 at 06:18, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0
>
> The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World leveraging TrustZone
> technology.
>
> This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> querying the FF-A framework from the secure world.
>
> The driver uses SMC32 calling convention which means using the first
> 32-bit data of the Xn registers.
>
> All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
> which has 64-bit version supported.
>
> Both 32-bit and 64-bit direct messaging are supported which allows both
> 32-bit and 64-bit clients to use the FF-A bus.
>
> In U-Boot FF-A design, FF-A is considered as a discoverable bus.
> The Secure World is considered as one entity to communicate with
> using the FF-A bus. FF-A communication is handled by one device and
> one instance (the bus). This FF-A driver takes care of all the
> interactions between Normal world and Secure World.
>
> The driver exports its operations to be used by upper layers.
>
> Exported operations:
>
> - partition_info_get
> - sync_send_receive
> - rxtx_unmap
>
> For more details please refer to the driver documentation [2].
>
> [1]: https://developer.arm.com/documentation/den0077/latest/
> [2]: doc/arch/arm64.ffa.rst
>
> 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>
>
> ---
>
> Changelog:
> ===============
>
> v8:
>
> * make ffa_get_partitions_info() second argument to be an SP count in both
>   modes
> * update ffa_bus_prvdata_get() to return a pointer rather than a pointer
>   address
> * remove packing from ffa_partition_info and ffa_send_direct_data structures
> * pass the FF-A bus device to the bus operations
>
> v7:
>
> * add support for 32-bit direct messaging
> * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> * improve the declaration of error handling mapping
> * stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported
>
> v6:
>
> * drop use of EFI runtime support (We decided with Linaro to add this later)
> * drop discovery from initcalls (discovery will be on demand by FF-A users)
> * set the alignment of the RX/TX buffers to the larger translation granule size
> * move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
> * update the documentation and move it to doc/arch/arm64.ffa.rst
>
> v4:
>
> * add doc/README.ffa.drv
> * moving the FF-A driver work to drivers/firmware/arm-ffa
> * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
>   #if defined by #if CONFIG_IS_ENABLED
> * improving error handling by mapping the FF-A errors to standard errors
>   and logs
> * replacing panics with an error log and returning an error code
> * improving features discovery in FFA_FEATURES by introducing
>   rxtx_min_pages private data field
> * add ffa_remove and ffa_unbind functions
> * improve how the driver behaves when bus discovery is done more than
>   once
>
> v3:
>
> * align the interfaces of the U-Boot FF-A driver with those in the linux
>   FF-A driver
> * remove the FF-A helper layer
> * make the U-Boot FF-A driver independent from EFI
> * provide an optional config that enables copying the driver data to EFI
>   runtime section at ExitBootServices service
> * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
>
> v2:
>
> * make FF-A bus discoverable using device_{bind, probe} APIs
> * remove device tree support
>
> v1:
>
> * introduce FF-A bus driver with device tree support
>
> MAINTAINERS                               |    7 +
>  doc/arch/arm64.ffa.rst                    |  218 ++++
>  doc/arch/index.rst                        |    1 +
>  drivers/Kconfig                           |    2 +
>  drivers/Makefile                          |    1 +
>  drivers/firmware/arm-ffa/Kconfig          |   30 +
>  drivers/firmware/arm-ffa/Makefile         |    6 +
>  drivers/firmware/arm-ffa/arm-ffa-uclass.c |   16 +
>  drivers/firmware/arm-ffa/arm_ffa_prv.h    |  200 ++++
>  drivers/firmware/arm-ffa/core.c           | 1315 +++++++++++++++++++++
>  include/arm_ffa.h                         |   97 ++
>  include/dm/uclass-id.h                    |    4 +
>  12 files changed, 1897 insertions(+)
>  create mode 100644 doc/arch/arm64.ffa.rst
>  create mode 100644 drivers/firmware/arm-ffa/Kconfig
>  create mode 100644 drivers/firmware/arm-ffa/Makefile
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
>  create mode 100644 drivers/firmware/arm-ffa/core.c
>  create mode 100644 include/arm_ffa.h

This looks mostly OK to me. I have a few comments below.
[..]

> diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> new file mode 100644
> index 0000000000..4eea7dc036
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> @@ -0,0 +1,200 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#ifndef __ARM_FFA_PRV_H
> +#define __ARM_FFA_PRV_H
> +
> +#include <arm_ffa.h>
> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
> +#include <linux/arm-smccc.h>
> +
> +/*
> + * This header is private. It is exclusively used by the FF-A driver
> + */

/* ...*/

is the single-line comment style

> +
> +/* FF-A core driver name */
> +#define FFA_DRV_NAME "arm_ffa"
> +
> +/* FF-A driver version definitions */
> +
> +#define MAJOR_VERSION_MASK             GENMASK(30, 16)
> +#define MINOR_VERSION_MASK             GENMASK(15, 0)
> +#define GET_FFA_MAJOR_VERSION(x)               \
> +                               ((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> +#define GET_FFA_MINOR_VERSION(x)               \
> +                               ((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> +#define PACK_VERSION_INFO(major, minor)                        \
> +       (FIELD_PREP(MAJOR_VERSION_MASK, (major)) |      \
> +        FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> +
> +#define FFA_MAJOR_VERSION              (1)
> +#define FFA_MINOR_VERSION              (0)
> +#define FFA_VERSION_1_0                \
> +                       PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> +
> +/* Endpoint ID mask (u-boot endpoint ID) */
> +
> +#define GET_SELF_ENDPOINT_ID_MASK              GENMASK(15, 0)
> +#define GET_SELF_ENDPOINT_ID(x)                \
> +                       ((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> +
> +#define PREP_SELF_ENDPOINT_ID_MASK             GENMASK(31, 16)
> +#define PREP_SELF_ENDPOINT_ID(x)               \
> +                       (FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> +
> +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> +
> +#define PREP_PART_ENDPOINT_ID_MASK             GENMASK(15, 0)
> +#define PREP_PART_ENDPOINT_ID(x)               \
> +                       (FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> +
> +/*
> + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> + */
> +
> +#define FFA_SMC(calling_convention, func_num)                          \
> +       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),   \
> +                          ARM_SMCCC_OWNER_STANDARD, (func_num))
> +
> +#define FFA_SMC_32(func_num)                           FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> +#define FFA_SMC_64(func_num)                           FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
> +
> +enum ffa_abis {
> +       FFA_ERROR                 = 0x60,
> +       FFA_SUCCESS               = 0x61,
> +       FFA_INTERRUPT             = 0x62,
> +       FFA_VERSION               = 0x63,
> +       FFA_FEATURES              = 0x64,
> +       FFA_RX_RELEASE            = 0x65,
> +       FFA_RXTX_MAP              = 0x66,
> +       FFA_RXTX_UNMAP            = 0x67,
> +       FFA_PARTITION_INFO_GET    = 0x68,
> +       FFA_ID_GET                = 0x69,
> +       FFA_RUN                   = 0x6D,
> +       FFA_MSG_SEND_DIRECT_REQ   = 0x6F,

Can you use lower-case hex consistently?

> +       FFA_MSG_SEND_DIRECT_RESP  = 0x70,
> +
> +       /* to be updated when adding new FFA IDs */
> +       FFA_FIRST_ID              = FFA_ERROR, /* lowest number ID*/
> +       FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/

not: spaces before */


> +};
> +
> +enum ffa_abi_errcode {
> +       NOT_SUPPORTED = 1,
> +       INVALID_PARAMETERS,
> +       NO_MEMORY,
> +       BUSY,
> +       INTERRUPTED,
> +       DENIED,
> +       RETRY,
> +       ABORTED,
> +       MAX_NUMBER_FFA_ERR
> +};
> +
> +/* container structure and helper macros to map between an FF-A error and relevant error log */
> +struct ffa_abi_errmap {
> +       char *err_str[MAX_NUMBER_FFA_ERR];
> +};
> +
> +#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);

that needs a comment

[..]

> +/**
> + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> + * @rxbuf:     virtual address of the RX buffer
> + * @txbuf:     virtual address of the TX buffer
> + * @rxtx_min_pages:    RX/TX buffers minimum size in pages
> + *
> + * Data structure hosting the virtual addresses of the mapped RX/TX buffers

Just a nit but it catches my eye. We know this is a struct. You can
just say "Hosts the ..."

[..]


> diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
> new file mode 100644
> index 0000000000..0b1f8e6a07
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/core.c
> @@ -0,0 +1,1315 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include "arm_ffa_prv.h"
> +#include <asm/global_data.h>
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/device-internal.h>
> +#include <dm/devres.h>
> +#include <dm/root.h>
> +#include <linux/errno.h>
> +#include <linux/sizes.h>
> +#include <log.h>
> +#include <malloc.h>
> +#include <string.h>
> +#include <uuid.h>

See this:

https://u-boot.readthedocs.io/en/latest/develop/codingstyle.html?highlight=style#include-files

[..]

> +/*
> + * Driver core functions
> + */
> +
> +/**
> + * ffa_remove_device - removes the arm_ffa device
> + * @dev:       the device to be removed
> + *
> + * This function makes sure the arm_ffa device is removed
> + * No need to free the kmalloced data when the device is destroyed.
> + * It's automatically done by devm management by
> + * device_remove() -> device_free() -> devres_release_probe().
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_remove_device(struct udevice *dev)
> +{
> +       int ret;
> +
> +       if (!dev) {
> +               ffa_err("no udevice found");
> +               return -ENODEV;
> +       }
> +
> +       ret = device_remove(dev, DM_REMOVE_NORMAL);
> +       if (ret) {
> +               ffa_err("unable to remove. err:%d\n", ret);
> +               return ret;
> +       }
> +
> +       ffa_info("device removed and freed");
> +
> +       ret = device_unbind(dev);
> +       if (ret) {
> +               ffa_err("unable to unbind. err:%d\n", ret);
> +               return ret;
> +       }
> +
> +       ffa_info("device unbound");
> +
> +       return 0;
> +}

Do we need this function? We should not be unbinding devices. Even
removing them should be done elsewhere  if needed. But why?

> +
> +/**
> + * ffa_device_get - create, bind and probe the arm_ffa device
> + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> + *       successfully)
> + *
> + * This function makes sure the arm_ffa device is
> + * created, bound to this driver, probed and ready to use.
> + * Arm FF-A transport is implemented through a single U-Boot
> + * device managing the FF-A bus (arm_ffa).
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_device_get(struct udevice **pdev)
> +{
> +       int ret;
> +       struct udevice *dev = NULL;
> +
> +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> +                         &dev);

Please add a DT binding. Even if only temporary, we need something for this.
[..]

> +static int ffa_get_version(void)
> +{
> +       u16 major, minor;
> +       ffa_value_t res = {0};
> +       int ffa_errno;
> +
> +       ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> +                       .a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
> +                       }, &res);
> +
> +       ffa_errno = res.a0;
> +       if (ffa_errno < 0) {
> +               ffa_print_error_log(FFA_VERSION, ffa_errno);
> +               return ffa_to_std_errno(ffa_errno);
> +       }
> +
> +       major = GET_FFA_MAJOR_VERSION(res.a0);
> +       minor = GET_FFA_MINOR_VERSION(res.a0);
> +
> +       ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> +                FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> +
> +       if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {

nit: Drop extra brackets

> +               ffa_info("Versions are compatible ");
> +
> +               ffa_priv_data->fwk_version = res.a0;
> +
> +               return 0;
> +       }
> +
> +       ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
> +               FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> +
> +       return -EPROTONOSUPPORT;
> +}
> +
> +/**
> + * ffa_get_endpoint_id - FFA_ID_GET handler function

I believe these should have () at the end, so:

ffa_get_endpoint_id() - FFA_ID_GET handler function

> + *
> + * This function implements FFA_ID_GET FF-A function
> + * to get from the secure world u-boot endpoint ID
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
[..]

> +/**
> + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> + *
> + * This  function  frees the RX/TX buffers
> + *
> + */
> +static void ffa_free_rxtx_buffers(void)
> +{
> +       ffa_info("Freeing RX/TX buffers");
> +
> +       if (ffa_priv_data->pair.rxbuf) {
> +               free((void *)ffa_priv_data->pair.rxbuf);

You can't cast an address to a pointer in this way. Should use
map_sysmem() or store a pointer.

> +               ffa_priv_data->pair.rxbuf = 0;
> +       }
> +
> +       if (ffa_priv_data->pair.txbuf) {
> +               free((void *)ffa_priv_data->pair.txbuf);
> +               ffa_priv_data->pair.txbuf = 0;
> +       }
> +}
> +[..]

> +       /*
> +        * make sure the buffers are cleared before use
> +        */
> +       memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
> +       memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);

Yes these should be pointers everywhere, since you are casting all the time.

> +
> +       return 0;
> +}
> +
[..]

> +/**
> + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> + *                                                     and saves it in the private structure

Can you fit all these titles on one line, like:

ffa_read_partitions_info() - Read partition information

<insert longer description here?>

> + * @count: The number of partitions queried
> + * @part_uuid: Pointer to the partition(s) UUID
> + *
> + * This function reads the partitions information
> + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> + * data structure.
> + *
> + * Return:
> + *
> + * The private data structure is updated with the partition(s) information
> + * 0 is returned on success. Otherwise, failure
> + */

[..]
[..]

> +static int ffa_msg_send_direct_req(struct udevice *dev, u16 dst_part_id,
> +                                  struct ffa_send_direct_data *msg, bool is_smc64)
> +{
> +       ffa_value_t res = {0};
> +       int ffa_errno;
> +       u64 req_mode, resp_mode;
> +
> +       if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
> +               return -EINVAL;

ffa_priv_data should be called 'priv' and attached to the device with
device_get_priv()
[..]

> +/**
> + * ffa_probe - The driver probe function
> + * @dev:       the arm_ffa device
> + *
> + * Probing is done at boot time and triggered by the uclass device discovery.
> + * At probe level the following actions are done:
> + *     - setting the conduit
> + *     - querying the FF-A framework version
> + *     - querying from secure world the u-boot endpoint ID
> + *     - querying from secure world the supported features of FFA_RXTX_MAP
> + *     - mapping the RX/TX buffers
> + *     - querying from secure world all the partitions information
> + *
> + * All data queried from secure world is saved in the resident private data structure.
> + *
> + * The probe will fail if either FF-A framework is not detected or the
> + * FF-A requests are not behaving correctly. This ensures that the
> + * driver is not installed and its operations are not exported to the clients.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_probe(struct udevice *dev)
> +{
> +       int ret;
> +
> +       ret = ffa_alloc_prvdata(dev);

don't do this, see above.

[..]

> diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> new file mode 100644
> index 0000000000..74b16174c2
> --- /dev/null
> +++ b/include/arm_ffa.h
> @@ -0,0 +1,97 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#ifndef __ARM_FFA_H
> +#define __ARM_FFA_H
> +
> +#include <linux/printk.h>
> +
> +/*
> + * This header is public. It can be used by clients to access
> + * data structures and definitions they need
> + */
> +
> +/*
> + * Macros for displaying logs
> + */
> +
> +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)

You could use log_info(), log_err()

> +
> +/*
> + * struct ffa_partition_info - Partition information descriptor
> + * @id:        Partition ID
> + * @exec_ctxt: Execution context count
> + * @properties:        Partition properties
> + *
> + * Data structure containing information about partitions instantiated in the system
> + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> + */
> +struct ffa_partition_info {
> +       u16 id;
> +       u16 exec_ctxt;
> +/* partition supports receipt of direct requests */
> +#define FFA_PARTITION_DIRECT_RECV      BIT(0)
> +/* partition can send direct requests. */
> +#define FFA_PARTITION_DIRECT_SEND      BIT(1)
> +/* partition can send and receive indirect messages. */
> +#define FFA_PARTITION_INDIRECT_MSG     BIT(2)
> +       u32 properties;
> +};
> +
> +/*
> + * struct ffa_send_direct_data - Data structure hosting the data
> + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * @data0-4:   Data read/written from/to x3-x7 registers
> + *
> + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> + * or read from FFA_MSG_SEND_DIRECT_RESP
> + */
> +
> +/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
> +struct ffa_send_direct_data {
> +       unsigned long data0; /* w3/x3 */
> +       unsigned long data1; /* w4/x4 */
> +       unsigned long data2; /* w5/x5 */
> +       unsigned long data3; /* w6/x6 */
> +       unsigned long data4; /* w7/x7 */
> +};
> +
> +struct udevice;
> +
> +/**
> + * struct ffa_bus_ops - The driver operations structure
> + * @partition_info_get:        callback for the FFA_PARTITION_INFO_GET
> + * @sync_send_receive: callback for the FFA_MSG_SEND_DIRECT_REQ
> + * @rxtx_unmap:        callback for the FFA_RXTX_UNMAP
> + *
> + * The data structure providing all the operations supported by the driver.
> + * This structure is EFI runtime resident.
> + */
> +struct ffa_bus_ops {
> +       int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
> +                                 u32 *sp_count, struct ffa_partition_info *buffer);
> +       int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
> +                                struct ffa_send_direct_data *msg,
> +                                bool is_smc64);
> +       int (*rxtx_unmap)(struct udevice *dev);
> +};

Shouldn't this be the .ops member in your driver?

> +
> +/**
> + * The device driver and the Uclass driver public functions
> + */
> +
> +/**
> + * ffa_bus_ops_get - driver operations getter
> + */
> +const struct ffa_bus_ops *ffa_bus_ops_get(void);

See how this is done in other uclasses, e.g. spi_get_ops()

Regards,
SImon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 04/10] arm_ffa: efi: unmap RX/TX buffers
  2022-11-22 13:17                                         ` [PATCH v8 04/10] arm_ffa: efi: unmap RX/TX buffers Abdellatif El Khlifi
@ 2022-11-23  2:09                                           ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2022-11-23  2:09 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	trini, u-boot, vishnu.banavath, xueliang.zhong

Hi Abdellatif,

On Tue, 22 Nov 2022 at 06:18, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> unmap RX/TX buffers at ExitBootServices()
>
> Unmapping the RX/TX buffers created by u-boot is needed before EFI
> runtime.

U-Boot

>
> At EFI runtime the linux kernel takes care of allocating its own RX/TX
> buffers and registering them with the secure world.
>
> Secure world should be using the RX/TX buffers created by the kernel.
> So, RX/TX buffers created by u-boot must be unmapped.

U-Boot

>
> 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>
>
> ---
>
> Changelog:
> ===============
>
> v8: pass NULL device pointer to the FF-A bus operation
> v7: replace debug() by log_err()
>
> lib/efi_loader/efi_boottime.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
>
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index 253f9f75ef..8949aca250 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -3,6 +3,9 @@
>   * EFI application boot time services
>   *
>   * Copyright (c) 2016 Alexander Graf
> + *
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>
>  #include <common.h>
> @@ -23,6 +26,10 @@
>  #include <asm/setjmp.h>
>  #include <linux/libfdt_env.h>
>
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
> +#include <arm_ffa.h>
> +#endif
> +

Can we include it always?

>  DECLARE_GLOBAL_DATA_PTR;
>
>  /* Task priority level */
> @@ -2178,6 +2185,12 @@ 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)

Can this use if() ?

I am not sure what this is being done in EFI code, though. We can use
device_remove(...DM_REMOVE_ACTIVE_ALL) which is designed to handle
this.

> +               /* 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");
> +#endif
> +
>         /* Patch out unsupported runtime function */
>         efi_runtime_detach();
>
> --
> 2.17.1
>

Regards,
SImon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 06/10] arm_ffa: introduce the FF-A Sandbox driver
  2022-11-22 13:17                                         ` [PATCH v8 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
@ 2022-11-23  2:09                                           ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2022-11-23  2:09 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	trini, u-boot, vishnu.banavath, xueliang.zhong

Hi Abdellatif,

On Tue, 22 Nov 2022 at 06:18, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> 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>
>
> ---
>
> 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/sandbox.rst                  |   1 +
>  drivers/firmware/arm-ffa/Kconfig              |   9 +-
>  drivers/firmware/arm-ffa/Makefile             |   1 +
>  drivers/firmware/arm-ffa/arm_ffa_prv.h        |  15 +-

Can those changes be done in the previous patch where you introduced this file?

>  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 aa4e87d9f8..9197344df4 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -270,6 +270,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 cff166b1c1..141ffd1f85 100644
> --- a/configs/sandbox64_defconfig
> +++ b/configs/sandbox64_defconfig
> @@ -258,3 +258,5 @@ CONFIG_FWU_MULTI_BANK_UPDATE=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

Please add one

[..]

> 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);

Against this needs to use driver model properly. There appears to be
no actual device??

>
> +#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 @@

This seems OK, but I am still confused as to why the device handling
is done outside driver model.

[..]

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  2022-11-22 13:17                                         ` [PATCH v8 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2022-11-23  2:09                                           ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2022-11-23  2:09 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	trini, u-boot, vishnu.banavath, xueliang.zhong

Hi Abdellatif,

On Tue, 22 Nov 2022 at 06:18, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add functional test cases for the FF-A core driver
>
> These tests rely on the FF-A Sandbox driver which helps in
>  inspecting the FF-A core driver.
>
> 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>
>
> ---
>
> Changelog:
> ===============
>
> v8:
>
>   * update partition_info_get() second argument to be an SP count
>   * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7: set the tests to use 64-bit direct messaging
>
> v4: align sandbox tests with the new FF-A driver interfaces
>  and new way of error handling
>
> v1: introduce sandbox tests
>
> MAINTAINERS      |   1 +
>  test/dm/Makefile |   2 +
>  test/dm/ffa.c    | 392 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 395 insertions(+)
>  create mode 100644 test/dm/ffa.c

This looks OK to me, but for sorting out how devices are bound /
probed and how to call into a uclass.

Also, just return 0, not CMD_RET_SUCCESS. This isn't actually a
command :-) Even if it were, 0 is better.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 08/10] arm_ffa: introduce armffa command Sandbox test
  2022-11-22 13:17                                         ` [PATCH v8 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2022-11-23  2:09                                           ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2022-11-23  2:09 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	trini, u-boot, vishnu.banavath, xueliang.zhong

On Tue, 22 Nov 2022 at 06:18, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add Sandbox test for the armffa command
>
> 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>
>
> ---
>
> Changelog:
> ===============
>
> v4: drop use of helper APIs
>
> v1: introduce armffa command sandbox test
>
> MAINTAINERS       |  1 +
>  test/cmd/Makefile |  2 ++
>  test/cmd/armffa.c | 39 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 42 insertions(+)
>  create mode 100644 test/cmd/armffa.c

Looks good except for the discovery.


>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7a2cabfb2d..2f1684ece7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -271,6 +271,7 @@ F:  doc/arch/arm64.ffa.rst
>  F:     drivers/firmware/arm-ffa/
>  F:     include/arm_ffa.h
>  F:     include/sandbox_arm_ffa.h
> +F:     test/cmd/armffa.c
>  F:     test/dm/ffa.c
>
>  ARM FREESCALE IMX
> diff --git a/test/cmd/Makefile b/test/cmd/Makefile
> index 6dd6e81875..4c40aefb3b 100644
> --- a/test/cmd/Makefile
> +++ b/test/cmd/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0+
>  #
>  # Copyright (c) 2013 Google, Inc
> +# (C) Copyright 2022 ARM Limited
>
>  ifdef CONFIG_HUSH_PARSER
>  obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
> @@ -18,5 +19,6 @@ obj-$(CONFIG_CMD_PINMUX) += pinmux.o
>  obj-$(CONFIG_CMD_PWM) += pwm.o
>  ifdef CONFIG_SANDBOX
>  obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
> +obj-$(CONFIG_SANDBOX_FFA) += armffa.o
>  endif
>  obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
> diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
> new file mode 100644
> index 0000000000..e04363ba63
> --- /dev/null
> +++ b/test/cmd/armffa.c
> @@ -0,0 +1,39 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Test for armffa command
> + *
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include <common.h>
> +#include <dm/test.h>
> +#include <sandbox_arm_ffa.h>
> +#include <string.h>
> +#include <test/test.h>
> +#include <test/ut.h>
> +
> +#define PING_CMD_SIZE 19
> +
> +/* Basic test of 'armffa' command */
> +static int dm_test_armffa_cmd(struct unit_test_state *uts)
> +{
> +       char ping_cmd[PING_CMD_SIZE] = {0};
> +
> +       ut_assertok(ffa_bus_discover(NULL));
> +
> +       /* armffa getpart <UUID> */
> +       ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
> +
> +       snprintf(ping_cmd, PING_CMD_SIZE, "armffa ping 0x%x", SANDBOX_SP1_ID);
> +
> +       /* armffa ping <ID> */
> +       ut_assertok(run_command(ping_cmd, 0));
> +
> +       /* armffa devlist */
> +       ut_assertok(run_command("armffa devlist", 0));
> +
> +       return CMD_RET_SUCCESS;
> +}
> +
> +DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
> --
> 2.17.1
>

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 05/10] arm_ffa: introduce armffa command
  2022-11-22 13:17                                         ` [PATCH v8 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2022-11-23  2:09                                           ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2022-11-23  2:09 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	trini, u-boot, vishnu.banavath, xueliang.zhong

 Hi Abdellatif,

On Tue, 22 Nov 2022 at 06:18, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Provide armffa command showcasing the use of the FF-A driver
>
> The armffa command allows to query secure partitions data from
> the secure world and exchanging messages with the partitions
> using 64-bit FF-A 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>
>
> ---
>
> Changelog:
> ===============
>
> v8:
>
> * update partition_info_get() second argument to be an SP count
> * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7:
>
> * adapt do_ffa_dev_list() following the recent update on
>   uclass_first_device/uclass_next_device functions (they return void now)
> * set armffa command to use 64-bit direct messaging
>
> v4:
>
> * remove pattern data in do_ffa_msg_send_direct_req
>
> v3:
>
> * use the new driver interfaces (partition_info_get, sync_send_receive)
>   in armffa command
>
> v2:
>
> * replace use of ffa_helper_init_device function by
>  ffa_helper_bus_discover
>
> v1:
>
> * introduce armffa command
>
> MAINTAINERS                      |   1 +
>  cmd/Kconfig                      |  10 ++
>  cmd/Makefile                     |   2 +
>  cmd/armffa.c                     | 237 +++++++++++++++++++++++++++++++
>  drivers/firmware/arm-ffa/Kconfig |   1 +
>  5 files changed, 251 insertions(+)
>  create mode 100644 cmd/armffa.c

needs doc/usage also

>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index dcd32cf83a..aa4e87d9f8 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -266,6 +266,7 @@ F:  configs/cortina_presidio-asic-pnand_defconfig
>  ARM FF-A
>  M:     Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>  S:     Maintained
> +F:     cmd/armffa.c
>  F:     doc/arch/arm64.ffa.rst
>  F:     drivers/firmware/arm-ffa/
>  F:     include/arm_ffa.h
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 1092fb9c91..060d87375f 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -924,6 +924,16 @@ endmenu
>
>  menu "Device access commands"
>
> +config CMD_ARMFFA
> +       bool "Arm FF-A test command"
> +       depends on ARM_FFA_TRANSPORT
> +       help
> +         Provides a test command for the Arm FF-A driver
> +         supported options:
> +               - Listing the partition(s) info
> +               - Sending a data pattern to the specified partition
> +               - Displaying the arm_ffa device info
> +
>  config CMD_ARMFLASH
>         #depends on FLASH_CFI_DRIVER
>         bool "armflash"
> diff --git a/cmd/Makefile b/cmd/Makefile
> index 2444d116c0..c600d90d39 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -12,6 +12,8 @@ obj-y += panic.o
>  obj-y += version.o
>
>  # command
> +
> +obj-$(CONFIG_CMD_ARMFFA) += armffa.o
>  obj-$(CONFIG_CMD_ACPI) += acpi.o
>  obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
>  obj-$(CONFIG_CMD_AES) += aes.o
> diff --git a/cmd/armffa.c b/cmd/armffa.c
> new file mode 100644
> index 0000000000..d2e8687bfb
> --- /dev/null
> +++ b/cmd/armffa.c
> @@ -0,0 +1,237 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include <arm_ffa.h>
> +#include <asm/io.h>
> +#include <common.h>
> +#include <command.h>
> +#include <dm.h>
> +#include <mapmem.h>
> +#include <stdlib.h>
> +
> +/**
> + * do_ffa_get_singular_partition_info - implementation of the getpart subcommand

do_ffa_get_singular_partition_info is too long!

> + * @cmdtp:             Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * This function queries the secure partition information which the UUID is provided
> + * as an argument. The function uses the arm_ffa driver partition_info_get operation
> + * to retrieve the data.
> + * The input UUID string is expected to be in big endian format.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +static int do_ffa_get_singular_partition_info(struct cmd_tbl *cmdtp, int flag, int argc,
> +                                             char *const argv[])
> +{
> +       u32 count = 0;
> +       int ret;
> +       struct ffa_partition_info *parts_info;
> +       u32 info_idx;
> +
> +       if (argc != 1)
> +               return -EINVAL;
> +
> +       /* Mode 1: getting the number of secure partitions */
> +       ret = ffa_bus_ops_get()->partition_info_get(NULL, argv[0], &count, NULL);
> +       if (ret != 0) {
> +               ffa_err("Failure in querying partitions count (error code: %d)", ret);
> +               return ret;
> +       }
> +
> +       if (!count) {
> +               ffa_info("No secure partition found");
> +               return ret;
> +       }
> +
> +       /*
> +        * pre-allocate a buffer to be filled by the driver
> +        * with ffa_partition_info structs
> +        */
> +
> +       ffa_info("Pre-allocating %d partition(s) info structures", count);
> +
> +       parts_info = calloc(count, sizeof(struct ffa_partition_info));
> +       if (!parts_info)
> +               return -EINVAL;
> +
> +       /*
> +        * ask the driver to fill the buffer with the SPs info
> +        */
> +
> +       ret = ffa_bus_ops_get()->partition_info_get(NULL, argv[0], &count, parts_info);
> +       if (ret != 0) {
> +               ffa_err("Failure in querying partition(s) info (error code: %d)", ret);
> +               free(parts_info);
> +               return ret;
> +       }
> +
> +       /*
> +        * SPs found , show the partition information
> +        */
> +       for (info_idx = 0; info_idx < count ; info_idx++) {
> +               ffa_info("Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x",
> +                        parts_info[info_idx].id,
> +                        parts_info[info_idx].exec_ctxt,
> +                        parts_info[info_idx].properties);
> +       }
> +
> +       free(parts_info);
> +
> +       return 0;
> +}
> +
> +/**
> + * do_ffa_msg_send_direct_req - implementation of the ping subcommand
> + * @cmdtp:             Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * This function sends data to the secure partition which the ID is provided
> + * as an argument. The function uses the arm_ffa driver sync_send_receive operation
> + * to send data.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +int  do_ffa_msg_send_direct_req(struct cmd_tbl *cmdtp, int flag, int argc,
> +                               char *const argv[])
> +{
> +       struct ffa_send_direct_data msg = {
> +                       .data0 = 0xaaaaaaaa,
> +                       .data1 = 0xbbbbbbbb,
> +                       .data2 = 0xcccccccc,
> +                       .data3 = 0xdddddddd,
> +                       .data4 = 0xeeeeeeee,
> +       };
> +       u16 part_id;
> +       int ret;
> +
> +       if (argc != 1)
> +               return -EINVAL;
> +
> +       errno = 0;
> +       part_id = strtoul(argv[0], NULL, 16);
> +
> +       if (errno) {
> +               ffa_err("Invalid partition ID");
> +               return -EINVAL;
> +       }
> +
> +       ret = ffa_bus_ops_get()->sync_send_receive(NULL, part_id, &msg, 1);

This needs to use driver model properly. Get a pointer to the device,
then call the uclass function in the header, which is implemented in
ffa-uclass.c - see how it is done in other uclasses.

> +       if (ret == 0) {

!ret

> +               u8 cnt;
> +
> +               ffa_info("SP response:\n[LSB]");
> +               for (cnt = 0;
> +                    cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
> +                    cnt++)
> +                       ffa_info("0x%llx", ((u64 *)&msg)[cnt]);
> +       } else {
> +               ffa_err("Sending direct request error (%d)", ret);
> +       }
> +
> +       return ret;
> +}
> +
> +/**
> + *do_ffa_dev_list - implementation of the devlist subcommand
> + * @cmdtp: [in]                Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * This function queries the devices belonging to the UCLASS_FFA
> + * class. Currently, one device is expected to show up: the arm_ffa device
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +int do_ffa_dev_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       struct udevice *dev = NULL;
> +       int i;
> +
> +       ffa_info("arm_ffa uclass entries:");
> +
> +       for (i = 0, uclass_first_device(UCLASS_FFA, &dev);
> +            dev;
> +            uclass_next_device(&dev), i++) {
> +               ffa_info("entry %d - instance %08x, ops %08x, plat %08x",
> +                        i,
> +                        (u32)map_to_sysmem(dev),
> +                        (u32)map_to_sysmem(dev->driver->ops),
> +                        (u32)map_to_sysmem(dev_get_plat(dev)));
> +       }
> +
> +       return 0;
> +}
> +
> +static struct cmd_tbl armffa_commands[] = {
> +       U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_get_singular_partition_info, "", ""),

do_getpart() is enough

> +       U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_msg_send_direct_req, "", ""),
> +       U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_dev_list, "", ""),
> +};
> +
> +/**
> + * do_armffa - the armffa command main function
> + * @cmdtp:     Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * This function identifies which armffa subcommand to run.
> + * Then, it makes sure the arm_ffa device is probed and
> + * ready for use.
> + * Then, it runs the subcommand.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       struct cmd_tbl *armffa_cmd;
> +       int ret;
> +
> +       if (argc < 2)
> +               return CMD_RET_USAGE;
> +
> +       armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
> +
> +       argc -= 2;
> +       argv += 2;
> +
> +       if (!armffa_cmd || argc > armffa_cmd->maxargs)
> +               return CMD_RET_USAGE;
> +
> +       ret = ffa_bus_discover(NULL);

No, this should be handled by uclass_first_device(UCLASS_FFFA) etc.

> +       if (ret != 0)
> +               return cmd_process_error(cmdtp, ret);
> +
> +       if (!ffa_bus_ops_get())
> +               return -EINVAL;
> +
> +       ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
> +
> +       return cmd_process_error(armffa_cmd, ret);
> +}
> +
> +U_BOOT_CMD(armffa, 4, 1, do_armffa,
> +          "Arm FF-A operations test command",
> +          "getpart <partition UUID>\n"
> +          "     - lists the partition(s) info\n"
> +          "ping <partition ID>\n"
> +          "     - sends a data pattern to the specified partition\n"
> +          "devlist\n"
> +          "     - displays the arm_ffa device info\n");
> diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> index e4914b9bc7..be4df89d23 100644
> --- a/drivers/firmware/arm-ffa/Kconfig
> +++ b/drivers/firmware/arm-ffa/Kconfig
> @@ -4,6 +4,7 @@ config ARM_FFA_TRANSPORT
>         bool "Enable Arm Firmware Framework for Armv8-A driver"
>         depends on DM && ARM64
>         select ARM_SMCCC
> +       select CMD_ARMFFA

imply would be better, unless turning it off breaks things?

>         select LIB_UUID
>         select DEVRES
>         help
> --
> 2.17.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-23  2:09                                           ` Simon Glass
@ 2022-11-24 13:21                                             ` Abdellatif El Khlifi
  2022-11-25 21:17                                               ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-11-24 13:21 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, nd, ilias.apalodimas, robh

On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
>  should be called 'priov' and should beHi Abdellatif,
> 
> On Tue, 22 Nov 2022 at 06:18, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0
> >
> > The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> > describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World leveraging TrustZone
> > technology.
> >
> > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > querying the FF-A framework from the secure world.
> >
> > The driver uses SMC32 calling convention which means using the first
> > 32-bit data of the Xn registers.
> >
> > All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
> > which has 64-bit version supported.
> >
> > Both 32-bit and 64-bit direct messaging are supported which allows both
> > 32-bit and 64-bit clients to use the FF-A bus.
> >
> > In U-Boot FF-A design, FF-A is considered as a discoverable bus.
> > The Secure World is considered as one entity to communicate with
> > using the FF-A bus. FF-A communication is handled by one device and
> > one instance (the bus). This FF-A driver takes care of all the
> > interactions between Normal world and Secure World.
> >
> > The driver exports its operations to be used by upper layers.
> >
> > Exported operations:
> >
> > - partition_info_get
> > - sync_send_receive
> > - rxtx_unmap
> >
> > For more details please refer to the driver documentation [2].
> >
> > [1]: https://developer.arm.com/documentation/den0077/latest/
> > [2]: doc/arch/arm64.ffa.rst
> >
> > 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>
> >
> > ---
> >
> > Changelog:
> > ===============
> >
> > v8:
> >
> > * make ffa_get_partitions_info() second argument to be an SP count in both
> >   modes
> > * update ffa_bus_prvdata_get() to return a pointer rather than a pointer
> >   address
> > * remove packing from ffa_partition_info and ffa_send_direct_data structures
> > * pass the FF-A bus device to the bus operations
> >
> > v7:
> >
> > * add support for 32-bit direct messaging
> > * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> > * improve the declaration of error handling mapping
> > * stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported
> >
> > v6:
> >
> > * drop use of EFI runtime support (We decided with Linaro to add this later)
> > * drop discovery from initcalls (discovery will be on demand by FF-A users)
> > * set the alignment of the RX/TX buffers to the larger translation granule size
> > * move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
> > * update the documentation and move it to doc/arch/arm64.ffa.rst
> >
> > v4:
> >
> > * add doc/README.ffa.drv
> > * moving the FF-A driver work to drivers/firmware/arm-ffa
> > * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
> >   #if defined by #if CONFIG_IS_ENABLED
> > * improving error handling by mapping the FF-A errors to standard errors
> >   and logs
> > * replacing panics with an error log and returning an error code
> > * improving features discovery in FFA_FEATURES by introducing
> >   rxtx_min_pages private data field
> > * add ffa_remove and ffa_unbind functions
> > * improve how the driver behaves when bus discovery is done more than
> >   once
> >
> > v3:
> >
> > * align the interfaces of the U-Boot FF-A driver with those in the linux
> >   FF-A driver
> > * remove the FF-A helper layer
> > * make the U-Boot FF-A driver independent from EFI
> > * provide an optional config that enables copying the driver data to EFI
> >   runtime section at ExitBootServices service
> > * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
> >
> > v2:
> >
> > * make FF-A bus discoverable using device_{bind, probe} APIs
> > * remove device tree support
> >
> > v1:
> >
> > * introduce FF-A bus driver with device tree support
> >
> > MAINTAINERS                               |    7 +
> >  doc/arch/arm64.ffa.rst                    |  218 ++++
> >  doc/arch/index.rst                        |    1 +
> >  drivers/Kconfig                           |    2 +
> >  drivers/Makefile                          |    1 +
> >  drivers/firmware/arm-ffa/Kconfig          |   30 +
> >  drivers/firmware/arm-ffa/Makefile         |    6 +
> >  drivers/firmware/arm-ffa/arm-ffa-uclass.c |   16 +
> >  drivers/firmware/arm-ffa/arm_ffa_prv.h    |  200 ++++
> >  drivers/firmware/arm-ffa/core.c           | 1315 +++++++++++++++++++++
> >  include/arm_ffa.h                         |   97 ++
> >  include/dm/uclass-id.h                    |    4 +
> >  12 files changed, 1897 insertions(+)
> >  create mode 100644 doc/arch/arm64.ffa.rst
> >  create mode 100644 drivers/firmware/arm-ffa/Kconfig
> >  create mode 100644 drivers/firmware/arm-ffa/Makefile
> >  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
> >  create mode 100644 drivers/firmware/arm-ffa/arm_ffa_prv.h
> >  create mode 100644 drivers/firmware/arm-ffa/core.c
> >  create mode 100644 include/arm_ffa.h
> 
> This looks mostly OK to me. I have a few comments below.
> [..]
> 
> > diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> > new file mode 100644
> > index 0000000000..4eea7dc036
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
> > @@ -0,0 +1,200 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_PRV_H
> > +#define __ARM_FFA_PRV_H
> > +
> > +#include <arm_ffa.h>
> > +#include <linux/bitfield.h>
> > +#include <linux/bitops.h>
> > +#include <linux/arm-smccc.h>
> > +
> > +/*
> > + * This header is private. It is exclusively used by the FF-A driver
> > + */
> 
> /* ...*/
> 
> is the single-line comment style
> 
> > +
> > +/* FF-A core driver name */
> > +#define FFA_DRV_NAME "arm_ffa"
> > +
> > +/* FF-A driver version definitions */
> > +
> > +#define MAJOR_VERSION_MASK             GENMASK(30, 16)
> > +#define MINOR_VERSION_MASK             GENMASK(15, 0)
> > +#define GET_FFA_MAJOR_VERSION(x)               \
> > +                               ((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> > +#define GET_FFA_MINOR_VERSION(x)               \
> > +                               ((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> > +#define PACK_VERSION_INFO(major, minor)                        \
> > +       (FIELD_PREP(MAJOR_VERSION_MASK, (major)) |      \
> > +        FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> > +
> > +#define FFA_MAJOR_VERSION              (1)
> > +#define FFA_MINOR_VERSION              (0)
> > +#define FFA_VERSION_1_0                \
> > +                       PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> > +
> > +/* Endpoint ID mask (u-boot endpoint ID) */
> > +
> > +#define GET_SELF_ENDPOINT_ID_MASK              GENMASK(15, 0)
> > +#define GET_SELF_ENDPOINT_ID(x)                \
> > +                       ((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> > +
> > +#define PREP_SELF_ENDPOINT_ID_MASK             GENMASK(31, 16)
> > +#define PREP_SELF_ENDPOINT_ID(x)               \
> > +                       (FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> > +
> > +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> > +
> > +#define PREP_PART_ENDPOINT_ID_MASK             GENMASK(15, 0)
> > +#define PREP_PART_ENDPOINT_ID(x)               \
> > +                       (FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> > +
> > +/*
> > + * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
> > + */
> > +
> > +#define FFA_SMC(calling_convention, func_num)                          \
> > +       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),   \
> > +                          ARM_SMCCC_OWNER_STANDARD, (func_num))
> > +
> > +#define FFA_SMC_32(func_num)                           FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> > +#define FFA_SMC_64(func_num)                           FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
> > +
> > +enum ffa_abis {
> > +       FFA_ERROR                 = 0x60,
> > +       FFA_SUCCESS               = 0x61,
> > +       FFA_INTERRUPT             = 0x62,
> > +       FFA_VERSION               = 0x63,
> > +       FFA_FEATURES              = 0x64,
> > +       FFA_RX_RELEASE            = 0x65,
> > +       FFA_RXTX_MAP              = 0x66,
> > +       FFA_RXTX_UNMAP            = 0x67,
> > +       FFA_PARTITION_INFO_GET    = 0x68,
> > +       FFA_ID_GET                = 0x69,
> > +       FFA_RUN                   = 0x6D,
> > +       FFA_MSG_SEND_DIRECT_REQ   = 0x6F,
> 
> Can you use lower-case hex consistently?
> 
> > +       FFA_MSG_SEND_DIRECT_RESP  = 0x70,
> > +
> > +       /* to be updated when adding new FFA IDs */
> > +       FFA_FIRST_ID              = FFA_ERROR, /* lowest number ID*/
> > +       FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* highest number ID*/
> 
> not: spaces before */
> 
> 
> > +};
> > +
> > +enum ffa_abi_errcode {
> > +       NOT_SUPPORTED = 1,
> > +       INVALID_PARAMETERS,
> > +       NO_MEMORY,
> > +       BUSY,
> > +       INTERRUPTED,
> > +       DENIED,
> > +       RETRY,
> > +       ABORTED,
> > +       MAX_NUMBER_FFA_ERR
> > +};
> > +
> > +/* container structure and helper macros to map between an FF-A error and relevant error log */
> > +struct ffa_abi_errmap {
> > +       char *err_str[MAX_NUMBER_FFA_ERR];
> > +};
> > +
> > +#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);
> 
> that needs a comment
> 
> [..]
> 
> > +/**
> > + * struct ffa_rxtxpair - structure hosting the RX/TX buffers virtual addresses
> > + * @rxbuf:     virtual address of the RX buffer
> > + * @txbuf:     virtual address of the TX buffer
> > + * @rxtx_min_pages:    RX/TX buffers minimum size in pages
> > + *
> > + * Data structure hosting the virtual addresses of the mapped RX/TX buffers
> 
> Just a nit but it catches my eye. We know this is a struct. You can
> just say "Hosts the ..."
> 
> [..]
> 
> 
> > diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
> > new file mode 100644
> > index 0000000000..0b1f8e6a07
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/core.c
> > @@ -0,0 +1,1315 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#include "arm_ffa_prv.h"
> > +#include <asm/global_data.h>
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <dm/device-internal.h>
> > +#include <dm/devres.h>
> > +#include <dm/root.h>
> > +#include <linux/errno.h>
> > +#include <linux/sizes.h>
> > +#include <log.h>
> > +#include <malloc.h>
> > +#include <string.h>
> > +#include <uuid.h>
> 
> See this:
> 
> https://u-boot.readthedocs.io/en/latest/develop/codingstyle.html?highlight=style#include-files
> 
> [..]
> 
> > +/*
> > + * Driver core functions
> > + */
> > +
> > +/**
> > + * ffa_remove_device - removes the arm_ffa device
> > + * @dev:       the device to be removed
> > + *
> > + * This function makes sure the arm_ffa device is removed
> > + * No need to free the kmalloced data when the device is destroyed.
> > + * It's automatically done by devm management by
> > + * device_remove() -> device_free() -> devres_release_probe().
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_remove_device(struct udevice *dev)
> > +{
> > +       int ret;
> > +
> > +       if (!dev) {
> > +               ffa_err("no udevice found");
> > +               return -ENODEV;
> > +       }
> > +
> > +       ret = device_remove(dev, DM_REMOVE_NORMAL);
> > +       if (ret) {
> > +               ffa_err("unable to remove. err:%d\n", ret);
> > +               return ret;
> > +       }
> > +
> > +       ffa_info("device removed and freed");
> > +
> > +       ret = device_unbind(dev);
> > +       if (ret) {
> > +               ffa_err("unable to unbind. err:%d\n", ret);
> > +               return ret;
> > +       }
> > +
> > +       ffa_info("device unbound");
> > +
> > +       return 0;
> > +}
> 
> Do we need this function? We should not be unbinding devices. Even
> removing them should be done elsewhere  if needed. But why?
> 
> > +
> > +/**
> > + * ffa_device_get - create, bind and probe the arm_ffa device
> > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > + *       successfully)
> > + *
> > + * This function makes sure the arm_ffa device is
> > + * created, bound to this driver, probed and ready to use.
> > + * Arm FF-A transport is implemented through a single U-Boot
> > + * device managing the FF-A bus (arm_ffa).
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_device_get(struct udevice **pdev)
> > +{
> > +       int ret;
> > +       struct udevice *dev = NULL;
> > +
> > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > +                         &dev);
> 
> Please add a DT binding. Even if only temporary, we need something for this.

Thanks for the feedback. I'm happy to address all the comments.

Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
about the following:

- DT is only for what we failed to make discoverable. For hardware, we're stuck
  with it. We shouldn't repeat that for software interfaces. This approach is 
  already applied in the FF-A kernel driver which comes with no DT support and
  discovers the bus with bus_register() API [1].

- FF-A bus in U-Boot is used on demand by clients. We don't want to set it up
  if no client is using it. For example, the EFI MM client tries to discover the
  FF-A bus, if it succeeds it uses it. Otherwise, it uses OP-TEE protocol [2].
  EFI MM client tries to discover the FF-A bus by calling ffa_bus_discover() 
  which is a discovery API provided by the FF-A core driver.

Here is an overview about what ffa_bus_discover() does :

client -> ffa_bus_discover() -> ffa_device_get() -> { device_bind() , device_probe() }

device_probe() -> ffa_probe() -> { at this stage the FF-A driver tries to discover the bus by executing FF-A discovery ABIs }

Let's see what Ilias and Rob think about FF-A discovery and DT support.

Cheers
Abdellatif

[1]: https://elixir.bootlin.com/linux/v6.1-rc4/source/drivers/firmware/arm_ffa/bus.c#L213
[2]: https://lore.kernel.org/all/20221122131751.22747-10-abdellatif.elkhlifi@arm.com/

> [..]
> 
> > +static int ffa_get_version(void)
> > +{
> > +       u16 major, minor;
> > +       ffa_value_t res = {0};
> > +       int ffa_errno;
> > +
> > +       ffa_priv_data->invoke_ffa_fn((ffa_value_t){
> > +                       .a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
> > +                       }, &res);
> > +
> > +       ffa_errno = res.a0;
> > +       if (ffa_errno < 0) {
> > +               ffa_print_error_log(FFA_VERSION, ffa_errno);
> > +               return ffa_to_std_errno(ffa_errno);
> > +       }
> > +
> > +       major = GET_FFA_MAJOR_VERSION(res.a0);
> > +       minor = GET_FFA_MINOR_VERSION(res.a0);
> > +
> > +       ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
> > +                FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +       if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
> 
> nit: Drop extra brackets
> 
> > +               ffa_info("Versions are compatible ");
> > +
> > +               ffa_priv_data->fwk_version = res.a0;
> > +
> > +               return 0;
> > +       }
> > +
> > +       ffa_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
> > +               FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> > +
> > +       return -EPROTONOSUPPORT;
> > +}
> > +
> > +/**
> > + * ffa_get_endpoint_id - FFA_ID_GET handler function
> 
> I believe these should have () at the end, so:
> 
> ffa_get_endpoint_id() - FFA_ID_GET handler function
> 
> > + *
> > + * This function implements FFA_ID_GET FF-A function
> > + * to get from the secure world u-boot endpoint ID
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> [..]
> 
> > +/**
> > + * ffa_free_rxtx_buffers - frees the RX/TX buffers
> > + *
> > + * This  function  frees the RX/TX buffers
> > + *
> > + */
> > +static void ffa_free_rxtx_buffers(void)
> > +{
> > +       ffa_info("Freeing RX/TX buffers");
> > +
> > +       if (ffa_priv_data->pair.rxbuf) {
> > +               free((void *)ffa_priv_data->pair.rxbuf);
> 
> You can't cast an address to a pointer in this way. Should use
> map_sysmem() or store a pointer.
> 
> > +               ffa_priv_data->pair.rxbuf = 0;
> > +       }
> > +
> > +       if (ffa_priv_data->pair.txbuf) {
> > +               free((void *)ffa_priv_data->pair.txbuf);
> > +               ffa_priv_data->pair.txbuf = 0;
> > +       }
> > +}
> > +[..]
> 
> > +       /*
> > +        * make sure the buffers are cleared before use
> > +        */
> > +       memset((void *)ffa_priv_data->pair.rxbuf, 0, bytes);
> > +       memset((void *)ffa_priv_data->pair.txbuf, 0, bytes);
> 
> Yes these should be pointers everywhere, since you are casting all the time.
> 
> > +
> > +       return 0;
> > +}
> > +
> [..]
> 
> > +/**
> > + * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
> > + *                                                     and saves it in the private structure
> 
> Can you fit all these titles on one line, like:
> 
> ffa_read_partitions_info() - Read partition information
> 
> <insert longer description here?>
> 
> > + * @count: The number of partitions queried
> > + * @part_uuid: Pointer to the partition(s) UUID
> > + *
> > + * This function reads the partitions information
> > + * returned by the FFA_PARTITION_INFO_GET and saves it in the private
> > + * data structure.
> > + *
> > + * Return:
> > + *
> > + * The private data structure is updated with the partition(s) information
> > + * 0 is returned on success. Otherwise, failure
> > + */
> 
> [..]
> [..]
> 
> > +static int ffa_msg_send_direct_req(struct udevice *dev, u16 dst_part_id,
> > +                                  struct ffa_send_direct_data *msg, bool is_smc64)
> > +{
> > +       ffa_value_t res = {0};
> > +       int ffa_errno;
> > +       u64 req_mode, resp_mode;
> > +
> > +       if (!ffa_priv_data || !ffa_priv_data->invoke_ffa_fn)
> > +               return -EINVAL;
> 
> ffa_priv_data should be called 'priv' and attached to the device with
> device_get_priv()
> [..]
> 
> > +/**
> > + * ffa_probe - The driver probe function
> > + * @dev:       the arm_ffa device
> > + *
> > + * Probing is done at boot time and triggered by the uclass device discovery.
> > + * At probe level the following actions are done:
> > + *     - setting the conduit
> > + *     - querying the FF-A framework version
> > + *     - querying from secure world the u-boot endpoint ID
> > + *     - querying from secure world the supported features of FFA_RXTX_MAP
> > + *     - mapping the RX/TX buffers
> > + *     - querying from secure world all the partitions information
> > + *
> > + * All data queried from secure world is saved in the resident private data structure.
> > + *
> > + * The probe will fail if either FF-A framework is not detected or the
> > + * FF-A requests are not behaving correctly. This ensures that the
> > + * driver is not installed and its operations are not exported to the clients.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int ffa_probe(struct udevice *dev)
> > +{
> > +       int ret;
> > +
> > +       ret = ffa_alloc_prvdata(dev);
> 
> don't do this, see above.
> 
> [..]
> 
> > diff --git a/include/arm_ffa.h b/include/arm_ffa.h
> > new file mode 100644
> > index 0000000000..74b16174c2
> > --- /dev/null
> > +++ b/include/arm_ffa.h
> > @@ -0,0 +1,97 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2022 ARM Limited
> > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + */
> > +
> > +#ifndef __ARM_FFA_H
> > +#define __ARM_FFA_H
> > +
> > +#include <linux/printk.h>
> > +
> > +/*
> > + * This header is public. It can be used by clients to access
> > + * data structures and definitions they need
> > + */
> > +
> > +/*
> > + * Macros for displaying logs
> > + */
> > +
> > +#define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
> > +#define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
> 
> You could use log_info(), log_err()
> 
> > +
> > +/*
> > + * struct ffa_partition_info - Partition information descriptor
> > + * @id:        Partition ID
> > + * @exec_ctxt: Execution context count
> > + * @properties:        Partition properties
> > + *
> > + * Data structure containing information about partitions instantiated in the system
> > + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> > + */
> > +struct ffa_partition_info {
> > +       u16 id;
> > +       u16 exec_ctxt;
> > +/* partition supports receipt of direct requests */
> > +#define FFA_PARTITION_DIRECT_RECV      BIT(0)
> > +/* partition can send direct requests. */
> > +#define FFA_PARTITION_DIRECT_SEND      BIT(1)
> > +/* partition can send and receive indirect messages. */
> > +#define FFA_PARTITION_INDIRECT_MSG     BIT(2)
> > +       u32 properties;
> > +};
> > +
> > +/*
> > + * struct ffa_send_direct_data - Data structure hosting the data
> > + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> > + * @data0-4:   Data read/written from/to x3-x7 registers
> > + *
> > + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> > + * or read from FFA_MSG_SEND_DIRECT_RESP
> > + */
> > +
> > +/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
> > +struct ffa_send_direct_data {
> > +       unsigned long data0; /* w3/x3 */
> > +       unsigned long data1; /* w4/x4 */
> > +       unsigned long data2; /* w5/x5 */
> > +       unsigned long data3; /* w6/x6 */
> > +       unsigned long data4; /* w7/x7 */
> > +};
> > +
> > +struct udevice;
> > +
> > +/**
> > + * struct ffa_bus_ops - The driver operations structure
> > + * @partition_info_get:        callback for the FFA_PARTITION_INFO_GET
> > + * @sync_send_receive: callback for the FFA_MSG_SEND_DIRECT_REQ
> > + * @rxtx_unmap:        callback for the FFA_RXTX_UNMAP
> > + *
> > + * The data structure providing all the operations supported by the driver.
> > + * This structure is EFI runtime resident.
> > + */
> > +struct ffa_bus_ops {
> > +       int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
> > +                                 u32 *sp_count, struct ffa_partition_info *buffer);
> > +       int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
> > +                                struct ffa_send_direct_data *msg,
> > +                                bool is_smc64);
> > +       int (*rxtx_unmap)(struct udevice *dev);
> > +};
> 
> Shouldn't this be the .ops member in your driver?
> 
> > +
> > +/**
> > + * The device driver and the Uclass driver public functions
> > + */
> > +
> > +/**
> > + * ffa_bus_ops_get - driver operations getter
> > + */
> > +const struct ffa_bus_ops *ffa_bus_ops_get(void);
> 
> See how this is done in other uclasses, e.g. spi_get_ops()
> 
> Regards,
> SImon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-24 13:21                                             ` Abdellatif El Khlifi
@ 2022-11-25 21:17                                               ` Simon Glass
  2022-11-28 16:22                                                 ` Rob Herring
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2022-11-25 21:17 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: U-Boot Mailing List, nd, Ilias Apalodimas, Rob Herring

Hi Abdellatif,

On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <
abdellatif.elkhlifi@arm.com> wrote:
>
> On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> >  should be called 'priov' and should beHi Abdellatif,
> >

[..]

> > > +/**
> > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > + * @pdev: the address of a device pointer (to be filled when the
arm_ffa bus device is created
> > > + *       successfully)
> > > + *
> > > + * This function makes sure the arm_ffa device is
> > > + * created, bound to this driver, probed and ready to use.
> > > + * Arm FF-A transport is implemented through a single U-Boot
> > > + * device managing the FF-A bus (arm_ffa).
> > > + *
> > > + * Return:
> > > + *
> > > + * 0 on success. Otherwise, failure
> > > + */
> > > +int ffa_device_get(struct udevice **pdev)
> > > +{
> > > +       int ret;
> > > +       struct udevice *dev = NULL;
> > > +
> > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa),
FFA_DRV_NAME, NULL, ofnode_null(),
> > > +                         &dev);
> >
> > Please add a DT binding. Even if only temporary, we need something for
this.
>
> Thanks for the feedback. I'm happy to address all the comments.
>
> Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob
Herring
> about the following:
>
> - DT is only for what we failed to make discoverable. For hardware, we're
stuck
>   with it. We shouldn't repeat that for software interfaces. This
approach is
>   already applied in the FF-A kernel driver which comes with no DT
support and
>   discovers the bus with bus_register() API [1].

This may be the UEFI view, but it is not how U-Boot works. This is not
something we are 'stuck' with. It is how we define what is present on a
device. This is how the PCI bus works in U-Boot. It is best practice in
U-Boot to use the device tree to make this things visible and configurable.
Unlike with Linux there is no other way to provide configuration needed by
these devices.

>
> - FF-A bus in U-Boot is used on demand by clients. We don't want to set
it up
>   if no client is using it. For example, the EFI MM client tries to
discover the
>   FF-A bus, if it succeeds it uses it. Otherwise, it uses OP-TEE protocol
[2].
>   EFI MM client tries to discover the FF-A bus by calling
ffa_bus_discover()
>   which is a discovery API provided by the FF-A core driver.

You are talking about probing, I think. Lazy init is build into U-Boot and
works fine. We don't need to invent another way to do it. Probe the device
if it is needed, but bind it always.

>
> Here is an overview about what ffa_bus_discover() does :
>
> client -> ffa_bus_discover() -> ffa_device_get() -> { device_bind() ,
device_probe() }
>
> device_probe() -> ffa_probe() -> { at this stage the FF-A driver tries to
discover the bus by executing FF-A discovery ABIs }

Yes it needs a bit of clean-up, to be honest. You need to add a device
pointer to the calls as well.

>
> Let's see what Ilias and Rob think about FF-A discovery and DT support.
>
> Cheers
> Abdellatif
>
> [1]:
https://elixir.bootlin.com/linux/v6.1-rc4/source/drivers/firmware/arm_ffa/bus.c#L213
> [2]:
https://lore.kernel.org/all/20221122131751.22747-10-abdellatif.elkhlifi@arm.com/
>

Regards,
SImon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-25 21:17                                               ` Simon Glass
@ 2022-11-28 16:22                                                 ` Rob Herring
  2022-11-28 16:26                                                   ` Ilias Apalodimas
  2022-12-04 19:22                                                   ` Simon Glass
  0 siblings, 2 replies; 478+ messages in thread
From: Rob Herring @ 2022-11-28 16:22 UTC (permalink / raw)
  To: Simon Glass
  Cc: Abdellatif El Khlifi, U-Boot Mailing List, nd, Ilias Apalodimas

On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Abdellatif,
>
> On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> >
> > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > >  should be called 'priov' and should beHi Abdellatif,
> > >
>
> [..]
>
> > > > +/**
> > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > + *       successfully)
> > > > + *
> > > > + * This function makes sure the arm_ffa device is
> > > > + * created, bound to this driver, probed and ready to use.
> > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > + * device managing the FF-A bus (arm_ffa).
> > > > + *
> > > > + * Return:
> > > > + *
> > > > + * 0 on success. Otherwise, failure
> > > > + */
> > > > +int ffa_device_get(struct udevice **pdev)
> > > > +{
> > > > +       int ret;
> > > > +       struct udevice *dev = NULL;
> > > > +
> > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > +                         &dev);
> > >
> > > Please add a DT binding. Even if only temporary, we need something for this.
> >
> > Thanks for the feedback. I'm happy to address all the comments.
> >
> > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > about the following:
> >
> > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> >   with it. We shouldn't repeat that for software interfaces. This approach is
> >   already applied in the FF-A kernel driver which comes with no DT support and
> >   discovers the bus with bus_register() API [1].
>
> This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.

Where do you get UEFI out of this?

It is the discoverability of hardware that is fixed (and we are stuck
with). We can't change hardware. The disoverability may be PCI
VID/PID, USB device descriptors, or nothing. We only use DT when those
are not sufficient. For a software interface, there is no reason to
make them non-discoverable as the interface can be fixed (at least for
new things like FF-A).

Rob

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-28 16:22                                                 ` Rob Herring
@ 2022-11-28 16:26                                                   ` Ilias Apalodimas
  2022-12-04 19:22                                                   ` Simon Glass
  1 sibling, 0 replies; 478+ messages in thread
From: Ilias Apalodimas @ 2022-11-28 16:26 UTC (permalink / raw)
  To: Rob Herring; +Cc: Simon Glass, Abdellatif El Khlifi, U-Boot Mailing List, nd

Hi all

On Mon, 28 Nov 2022 at 18:22, Rob Herring <robh@kernel.org> wrote:
>
> On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Abdellatif,
> >
> > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > >
> > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > >  should be called 'priov' and should beHi Abdellatif,
> > > >
> >
> > [..]
> >
> > > > > +/**
> > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > + *       successfully)
> > > > > + *
> > > > > + * This function makes sure the arm_ffa device is
> > > > > + * created, bound to this driver, probed and ready to use.
> > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > + *
> > > > > + * Return:
> > > > > + *
> > > > > + * 0 on success. Otherwise, failure
> > > > > + */
> > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > +{
> > > > > +       int ret;
> > > > > +       struct udevice *dev = NULL;
> > > > > +
> > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > +                         &dev);
> > > >
> > > > Please add a DT binding. Even if only temporary, we need something for this.
> > >
> > > Thanks for the feedback. I'm happy to address all the comments.
> > >
> > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > about the following:
> > >
> > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > >   already applied in the FF-A kernel driver which comes with no DT support and
> > >   discovers the bus with bus_register() API [1].
> >
> > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
>
> Where do you get UEFI out of this?
>
> It is the discoverability of hardware that is fixed (and we are stuck
> with). We can't change hardware. The disoverability may be PCI
> VID/PID, USB device descriptors, or nothing. We only use DT when those
> are not sufficient. For a software interface, there is no reason to
> make them non-discoverable as the interface can be fixed (at least for
> new things like FF-A).

I'll agree with Rob here.  In fact the first version of the patchset
*did* have this as a DT node.  We explicitly asked Abdellatif to
change this, so u-boot and the linux kernel can have an identical
approach in discovering FF-A

Regards
/Ilias

>
> Rob

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-11-28 16:22                                                 ` Rob Herring
  2022-11-28 16:26                                                   ` Ilias Apalodimas
@ 2022-12-04 19:22                                                   ` Simon Glass
  2022-12-05 15:49                                                     ` Rob Herring
  1 sibling, 1 reply; 478+ messages in thread
From: Simon Glass @ 2022-12-04 19:22 UTC (permalink / raw)
  To: Rob Herring
  Cc: Abdellatif El Khlifi, U-Boot Mailing List, nd, Ilias Apalodimas

Hi Rob,

On Tue, 29 Nov 2022 at 05:22, Rob Herring <robh@kernel.org> wrote:
>
> On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Abdellatif,
> >
> > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > >
> > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > >  should be called 'priov' and should beHi Abdellatif,
> > > >
> >
> > [..]
> >
> > > > > +/**
> > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > + *       successfully)
> > > > > + *
> > > > > + * This function makes sure the arm_ffa device is
> > > > > + * created, bound to this driver, probed and ready to use.
> > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > + *
> > > > > + * Return:
> > > > > + *
> > > > > + * 0 on success. Otherwise, failure
> > > > > + */
> > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > +{
> > > > > +       int ret;
> > > > > +       struct udevice *dev = NULL;
> > > > > +
> > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > +                         &dev);
> > > >
> > > > Please add a DT binding. Even if only temporary, we need something for this.
> > >
> > > Thanks for the feedback. I'm happy to address all the comments.
> > >
> > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > about the following:
> > >
> > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > >   already applied in the FF-A kernel driver which comes with no DT support and
> > >   discovers the bus with bus_register() API [1].
> >
> > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
>
> Where do you get UEFI out of this?

I assume it was UEFI as there was no discussion about this in U-Boot.
Which firmware project was consulted about this?

>
> It is the discoverability of hardware that is fixed (and we are stuck
> with). We can't change hardware. The disoverability may be PCI
> VID/PID, USB device descriptors, or nothing. We only use DT when those
> are not sufficient. For a software interface, there is no reason to
> make them non-discoverable as the interface can be fixed (at least for
> new things like FF-A).

Here I am talking about the controller itself, the top-level node in
the device tree. For PCI this is a device tree node and it should be
the same here. So I am not saying that the devices on the bus need to
be in the device tree (that can be optional, but may be useful in some
situations where it is status and known). We need something like:

ff-a {
    compatible = "something";
};

I don't know what mechanism is actually used to communicate with it,
but that will be enough to get the top-level driver started.

If Linux does not want to use the node, that it another thing, but I
respectfully request that U-Boot's needs be considered more carefully.
I'd also like to see more willingness to accommodate open-source
software in these designs.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-12-04 19:22                                                   ` Simon Glass
@ 2022-12-05 15:49                                                     ` Rob Herring
  2022-12-19 11:12                                                       ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Rob Herring @ 2022-12-05 15:49 UTC (permalink / raw)
  To: Simon Glass
  Cc: Abdellatif El Khlifi, U-Boot Mailing List, nd, Ilias Apalodimas

On Sun, Dec 4, 2022 at 1:22 PM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Rob,
>
> On Tue, 29 Nov 2022 at 05:22, Rob Herring <robh@kernel.org> wrote:
> >
> > On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Abdellatif,
> > >
> > > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > > >
> > > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > > >  should be called 'priov' and should beHi Abdellatif,
> > > > >
> > >
> > > [..]
> > >
> > > > > > +/**
> > > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > > + *       successfully)
> > > > > > + *
> > > > > > + * This function makes sure the arm_ffa device is
> > > > > > + * created, bound to this driver, probed and ready to use.
> > > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > > + *
> > > > > > + * Return:
> > > > > > + *
> > > > > > + * 0 on success. Otherwise, failure
> > > > > > + */
> > > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > > +{
> > > > > > +       int ret;
> > > > > > +       struct udevice *dev = NULL;
> > > > > > +
> > > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > > +                         &dev);
> > > > >
> > > > > Please add a DT binding. Even if only temporary, we need something for this.
> > > >
> > > > Thanks for the feedback. I'm happy to address all the comments.
> > > >
> > > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > > about the following:
> > > >
> > > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > > >   already applied in the FF-A kernel driver which comes with no DT support and
> > > >   discovers the bus with bus_register() API [1].
> > >
> > > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
> >
> > Where do you get UEFI out of this?
>
> I assume it was UEFI as there was no discussion about this in U-Boot.
> Which firmware project was consulted about this?
>
> >
> > It is the discoverability of hardware that is fixed (and we are stuck
> > with). We can't change hardware. The disoverability may be PCI
> > VID/PID, USB device descriptors, or nothing. We only use DT when those
> > are not sufficient. For a software interface, there is no reason to
> > make them non-discoverable as the interface can be fixed (at least for
> > new things like FF-A).
>
> Here I am talking about the controller itself, the top-level node in
> the device tree. For PCI this is a device tree node and it should be
> the same here. So I am not saying that the devices on the bus need to
> be in the device tree (that can be optional, but may be useful in some
> situations where it is status and known).

Sure, the PCI host bridges are not discoverable, have a bunch of
resources, and do need to be in DT. The downstream devices only do if
they have extra resources such as when a device is soldered down on a
board rather than a standard slot.

> We need something like:
>
> ff-a {
>     compatible = "something";
> };
>
> I don't know what mechanism is actually used to communicate with it,
> but that will be enough to get the top-level driver started.

There's discovery of FF-A itself and then discovery of FF-A features
(e.g. partitions). Both of those are discoverable without DT. The
first is done by checking the SMCCC version, then checking for FF-A
presence and features. Putting this into DT is redundant. Worse, what
if they disagree?

> If Linux does not want to use the node, that it another thing, but I
> respectfully request that U-Boot's needs be considered more carefully.

It's not really a big deal for just one compatible. It's the next 10
firmware things Arm comes up with. Or the let's add one property at a
time binding (mis)design that happens once we have a binding.

> I'd also like to see more willingness to accommodate open-source
> software in these designs.

I'm not sure what you are asking for here. Are you talking about FF-A
and Arm firmware interfaces itself, the DT binding for it, or
something else? I'd agree on the first part. I only saw this when the
binding landed on my plate. For bindings themselves, the firehose is
there. I can't pick out what you or others care and don't care about.
I try to steer common things to the devicetree-spec list, but there's
not that many things that come up really.

Rob

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-12-05 15:49                                                     ` Rob Herring
@ 2022-12-19 11:12                                                       ` Abdellatif El Khlifi
  2022-12-19 19:20                                                         ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2022-12-19 11:12 UTC (permalink / raw)
  To: Simon Glass
  Cc: ilias.apalodimas, jens.wiklander, robh, achin.gupta, trini,
	xueliang.zhong, nd, u-boot

On Mon, Dec 05, 2022 at 09:49:30AM -0600, Rob Herring wrote:
> On Sun, Dec 4, 2022 at 1:22 PM Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Rob,
> >
> > On Tue, 29 Nov 2022 at 05:22, Rob Herring <robh@kernel.org> wrote:
> > >
> > > On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Abdellatif,
> > > >
> > > > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > > > >
> > > > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > > > >  should be called 'priov' and should beHi Abdellatif,
> > > > > >
> > > >
> > > > [..]
> > > >
> > > > > > > +/**
> > > > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > > > + *       successfully)
> > > > > > > + *
> > > > > > > + * This function makes sure the arm_ffa device is
> > > > > > > + * created, bound to this driver, probed and ready to use.
> > > > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > > > + *
> > > > > > > + * Return:
> > > > > > > + *
> > > > > > > + * 0 on success. Otherwise, failure
> > > > > > > + */
> > > > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > > > +{
> > > > > > > +       int ret;
> > > > > > > +       struct udevice *dev = NULL;
> > > > > > > +
> > > > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > > > +                         &dev);
> > > > > >
> > > > > > Please add a DT binding. Even if only temporary, we need something for this.
> > > > >
> > > > > Thanks for the feedback. I'm happy to address all the comments.
> > > > >
> > > > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > > > about the following:
> > > > >
> > > > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > > > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > > > >   already applied in the FF-A kernel driver which comes with no DT support and
> > > > >   discovers the bus with bus_register() API [1].
> > > >
> > > > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
> > >
> > > Where do you get UEFI out of this?
> >
> > I assume it was UEFI as there was no discussion about this in U-Boot.
> > Which firmware project was consulted about this?
> >
> > >
> > > It is the discoverability of hardware that is fixed (and we are stuck
> > > with). We can't change hardware. The disoverability may be PCI
> > > VID/PID, USB device descriptors, or nothing. We only use DT when those
> > > are not sufficient. For a software interface, there is no reason to
> > > make them non-discoverable as the interface can be fixed (at least for
> > > new things like FF-A).
> >
> > Here I am talking about the controller itself, the top-level node in
> > the device tree. For PCI this is a device tree node and it should be
> > the same here. So I am not saying that the devices on the bus need to
> > be in the device tree (that can be optional, but may be useful in some
> > situations where it is status and known).
> 
> Sure, the PCI host bridges are not discoverable, have a bunch of
> resources, and do need to be in DT. The downstream devices only do if
> they have extra resources such as when a device is soldered down on a
> board rather than a standard slot.
> 
> > We need something like:
> >
> > ff-a {
> >     compatible = "something";
> > };
> >
> > I don't know what mechanism is actually used to communicate with it,
> > but that will be enough to get the top-level driver started.
> 
> There's discovery of FF-A itself and then discovery of FF-A features
> (e.g. partitions). Both of those are discoverable without DT. The
> first is done by checking the SMCCC version, then checking for FF-A
> presence and features. Putting this into DT is redundant. Worse, what
> if they disagree?

Hi Simon,

Do you agree with Rob, Ilias and myself that it makes more sense 
FF-A bus is discovered without a DT node and following the same approach as
Linux ? (FF-A bus doesn't have a HW controller and is a purely SW bus,
no configuration/description needed at DT level).

Your suggestions are always welcome.

cheers

> 
> > If Linux does not want to use the node, that it another thing, but I
> > respectfully request that U-Boot's needs be considered more carefully.
> 
> It's not really a big deal for just one compatible. It's the next 10
> firmware things Arm comes up with. Or the let's add one property at a
> time binding (mis)design that happens once we have a binding.
> 
> > I'd also like to see more willingness to accommodate open-source
> > software in these designs.
> 
> I'm not sure what you are asking for here. Are you talking about FF-A
> and Arm firmware interfaces itself, the DT binding for it, or
> something else? I'd agree on the first part. I only saw this when the
> binding landed on my plate. For bindings themselves, the firehose is
> there. I can't pick out what you or others care and don't care about.
> I try to steer common things to the devicetree-spec list, but there's
> not that many things that come up really.
> 
> Rob

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-12-19 11:12                                                       ` Abdellatif El Khlifi
@ 2022-12-19 19:20                                                         ` Simon Glass
  2023-01-12  2:10                                                           ` Rob Herring
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2022-12-19 19:20 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: ilias.apalodimas, jens.wiklander, robh, achin.gupta, trini,
	xueliang.zhong, nd, u-boot

Hi Abdellatif,

On Mon, 19 Dec 2022 at 04:12, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> On Mon, Dec 05, 2022 at 09:49:30AM -0600, Rob Herring wrote:
> > On Sun, Dec 4, 2022 at 1:22 PM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Rob,
> > >
> > > On Tue, 29 Nov 2022 at 05:22, Rob Herring <robh@kernel.org> wrote:
> > > >
> > > > On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > Hi Abdellatif,
> > > > >
> > > > > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > > > > >
> > > > > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > > > > >  should be called 'priov' and should beHi Abdellatif,
> > > > > > >
> > > > >
> > > > > [..]
> > > > >
> > > > > > > > +/**
> > > > > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > > > > + *       successfully)
> > > > > > > > + *
> > > > > > > > + * This function makes sure the arm_ffa device is
> > > > > > > > + * created, bound to this driver, probed and ready to use.
> > > > > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > > > > + *
> > > > > > > > + * Return:
> > > > > > > > + *
> > > > > > > > + * 0 on success. Otherwise, failure
> > > > > > > > + */
> > > > > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > > > > +{
> > > > > > > > +       int ret;
> > > > > > > > +       struct udevice *dev = NULL;
> > > > > > > > +
> > > > > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > > > > +                         &dev);
> > > > > > >
> > > > > > > Please add a DT binding. Even if only temporary, we need something for this.
> > > > > >
> > > > > > Thanks for the feedback. I'm happy to address all the comments.
> > > > > >
> > > > > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > > > > about the following:
> > > > > >
> > > > > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > > > > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > > > > >   already applied in the FF-A kernel driver which comes with no DT support and
> > > > > >   discovers the bus with bus_register() API [1].
> > > > >
> > > > > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
> > > >
> > > > Where do you get UEFI out of this?
> > >
> > > I assume it was UEFI as there was no discussion about this in U-Boot.
> > > Which firmware project was consulted about this?
> > >
> > > >
> > > > It is the discoverability of hardware that is fixed (and we are stuck
> > > > with). We can't change hardware. The disoverability may be PCI
> > > > VID/PID, USB device descriptors, or nothing. We only use DT when those
> > > > are not sufficient. For a software interface, there is no reason to
> > > > make them non-discoverable as the interface can be fixed (at least for
> > > > new things like FF-A).
> > >
> > > Here I am talking about the controller itself, the top-level node in
> > > the device tree. For PCI this is a device tree node and it should be
> > > the same here. So I am not saying that the devices on the bus need to
> > > be in the device tree (that can be optional, but may be useful in some
> > > situations where it is status and known).
> >
> > Sure, the PCI host bridges are not discoverable, have a bunch of
> > resources, and do need to be in DT. The downstream devices only do if
> > they have extra resources such as when a device is soldered down on a
> > board rather than a standard slot.
> >
> > > We need something like:
> > >
> > > ff-a {
> > >     compatible = "something";
> > > };
> > >
> > > I don't know what mechanism is actually used to communicate with it,
> > > but that will be enough to get the top-level driver started.
> >
> > There's discovery of FF-A itself and then discovery of FF-A features
> > (e.g. partitions). Both of those are discoverable without DT. The
> > first is done by checking the SMCCC version, then checking for FF-A
> > presence and features. Putting this into DT is redundant. Worse, what
> > if they disagree?
>
> Hi Simon,
>
> Do you agree with Rob, Ilias and myself that it makes more sense
> FF-A bus is discovered without a DT node and following the same approach as
> Linux ? (FF-A bus doesn't have a HW controller and is a purely SW bus,
> no configuration/description needed at DT level).
>
> Your suggestions are always welcome.

I'm sorry I don't agree with that. It does need a compatible string,
like PCI has. You can just add it in U-Boot if Linux won't accept the
binding.

Rob, if you are here I think the U-Boot DM bindings seem to have
stalled. What is needed to get these in?

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2022-12-19 19:20                                                         ` Simon Glass
@ 2023-01-12  2:10                                                           ` Rob Herring
  2023-01-12 23:43                                                             ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Rob Herring @ 2023-01-12  2:10 UTC (permalink / raw)
  To: Simon Glass
  Cc: Abdellatif El Khlifi, ilias.apalodimas, jens.wiklander,
	achin.gupta, trini, xueliang.zhong, nd, u-boot

On Mon, Dec 19, 2022 at 1:21 PM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Abdellatif,
>
> On Mon, 19 Dec 2022 at 04:12, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > On Mon, Dec 05, 2022 at 09:49:30AM -0600, Rob Herring wrote:
> > > On Sun, Dec 4, 2022 at 1:22 PM Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Rob,
> > > >
> > > > On Tue, 29 Nov 2022 at 05:22, Rob Herring <robh@kernel.org> wrote:
> > > > >
> > > > > On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > Hi Abdellatif,
> > > > > >
> > > > > > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > >
> > > > > > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > > > > > >  should be called 'priov' and should beHi Abdellatif,
> > > > > > > >
> > > > > >
> > > > > > [..]
> > > > > >
> > > > > > > > > +/**
> > > > > > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > > > > > + *       successfully)
> > > > > > > > > + *
> > > > > > > > > + * This function makes sure the arm_ffa device is
> > > > > > > > > + * created, bound to this driver, probed and ready to use.
> > > > > > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > > > > > + *
> > > > > > > > > + * Return:
> > > > > > > > > + *
> > > > > > > > > + * 0 on success. Otherwise, failure
> > > > > > > > > + */
> > > > > > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > > > > > +{
> > > > > > > > > +       int ret;
> > > > > > > > > +       struct udevice *dev = NULL;
> > > > > > > > > +
> > > > > > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > > > > > +                         &dev);
> > > > > > > >
> > > > > > > > Please add a DT binding. Even if only temporary, we need something for this.
> > > > > > >
> > > > > > > Thanks for the feedback. I'm happy to address all the comments.
> > > > > > >
> > > > > > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > > > > > about the following:
> > > > > > >
> > > > > > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > > > > > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > > > > > >   already applied in the FF-A kernel driver which comes with no DT support and
> > > > > > >   discovers the bus with bus_register() API [1].
> > > > > >
> > > > > > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
> > > > >
> > > > > Where do you get UEFI out of this?
> > > >
> > > > I assume it was UEFI as there was no discussion about this in U-Boot.
> > > > Which firmware project was consulted about this?
> > > >
> > > > >
> > > > > It is the discoverability of hardware that is fixed (and we are stuck
> > > > > with). We can't change hardware. The disoverability may be PCI
> > > > > VID/PID, USB device descriptors, or nothing. We only use DT when those
> > > > > are not sufficient. For a software interface, there is no reason to
> > > > > make them non-discoverable as the interface can be fixed (at least for
> > > > > new things like FF-A).
> > > >
> > > > Here I am talking about the controller itself, the top-level node in
> > > > the device tree. For PCI this is a device tree node and it should be
> > > > the same here. So I am not saying that the devices on the bus need to
> > > > be in the device tree (that can be optional, but may be useful in some
> > > > situations where it is status and known).
> > >
> > > Sure, the PCI host bridges are not discoverable, have a bunch of
> > > resources, and do need to be in DT. The downstream devices only do if
> > > they have extra resources such as when a device is soldered down on a
> > > board rather than a standard slot.
> > >
> > > > We need something like:
> > > >
> > > > ff-a {
> > > >     compatible = "something";
> > > > };
> > > >
> > > > I don't know what mechanism is actually used to communicate with it,
> > > > but that will be enough to get the top-level driver started.
> > >
> > > There's discovery of FF-A itself and then discovery of FF-A features
> > > (e.g. partitions). Both of those are discoverable without DT. The
> > > first is done by checking the SMCCC version, then checking for FF-A
> > > presence and features. Putting this into DT is redundant. Worse, what
> > > if they disagree?
> >
> > Hi Simon,
> >
> > Do you agree with Rob, Ilias and myself that it makes more sense
> > FF-A bus is discovered without a DT node and following the same approach as
> > Linux ? (FF-A bus doesn't have a HW controller and is a purely SW bus,
> > no configuration/description needed at DT level).
> >
> > Your suggestions are always welcome.
>
> I'm sorry I don't agree with that. It does need a compatible string,
> like PCI has. You can just add it in U-Boot if Linux won't accept the
> binding.

It's not like PCI as the host side of PCI has non-discoverable resources.

This all could have been designed better, but hindsight is 20/20 and
things evolved step by step. There are a bunch of firmware services
that are all behind SMCCC. The first (upstream) was PSCI. IIRC, SMCCC
was invented a bit after that, but generalized PSCI for other
services. Since then more have been added. More services get added one
by one and yes we added bindings for them. Because what's one more...
But that really needs to stop. We're stuck with h/w that's not
discoverable, there's zero reason to do that with s/w interfaces. If
we could redo everything, we'd have a node for SMCCC and that's it
unless there's h/w resources provided to the rest of DT. But we can't,
so SMCCC is discovered by the presence of PSCI.

Rob

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-12  2:10                                                           ` Rob Herring
@ 2023-01-12 23:43                                                             ` Simon Glass
  2023-01-13 10:44                                                               ` Abdellatif El Khlifi
  2023-01-18  2:51                                                               ` Rob Herring
  0 siblings, 2 replies; 478+ messages in thread
From: Simon Glass @ 2023-01-12 23:43 UTC (permalink / raw)
  To: Rob Herring
  Cc: Abdellatif El Khlifi, ilias.apalodimas, jens.wiklander,
	achin.gupta, trini, xueliang.zhong, nd, u-boot

Hi Rob,

On Wed, 11 Jan 2023 at 19:10, Rob Herring <robh@kernel.org> wrote:
>
> On Mon, Dec 19, 2022 at 1:21 PM Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Abdellatif,
> >
> > On Mon, 19 Dec 2022 at 04:12, Abdellatif El Khlifi
> > <abdellatif.elkhlifi@arm.com> wrote:
> > >
> > > On Mon, Dec 05, 2022 at 09:49:30AM -0600, Rob Herring wrote:
> > > > On Sun, Dec 4, 2022 at 1:22 PM Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > Hi Rob,
> > > > >
> > > > > On Tue, 29 Nov 2022 at 05:22, Rob Herring <robh@kernel.org> wrote:
> > > > > >
> > > > > > On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > >
> > > > > > > Hi Abdellatif,
> > > > > > >
> > > > > > > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > > >
> > > > > > > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > > > > > > >  should be called 'priov' and should beHi Abdellatif,
> > > > > > > > >
> > > > > > >
> > > > > > > [..]
> > > > > > >
> > > > > > > > > > +/**
> > > > > > > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > > > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > > > > > > + *       successfully)
> > > > > > > > > > + *
> > > > > > > > > > + * This function makes sure the arm_ffa device is
> > > > > > > > > > + * created, bound to this driver, probed and ready to use.
> > > > > > > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > > > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > > > > > > + *
> > > > > > > > > > + * Return:
> > > > > > > > > > + *
> > > > > > > > > > + * 0 on success. Otherwise, failure
> > > > > > > > > > + */
> > > > > > > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > > > > > > +{
> > > > > > > > > > +       int ret;
> > > > > > > > > > +       struct udevice *dev = NULL;
> > > > > > > > > > +
> > > > > > > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > > > > > > +                         &dev);
> > > > > > > > >
> > > > > > > > > Please add a DT binding. Even if only temporary, we need something for this.
> > > > > > > >
> > > > > > > > Thanks for the feedback. I'm happy to address all the comments.
> > > > > > > >
> > > > > > > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > > > > > > about the following:
> > > > > > > >
> > > > > > > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > > > > > > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > > > > > > >   already applied in the FF-A kernel driver which comes with no DT support and
> > > > > > > >   discovers the bus with bus_register() API [1].
> > > > > > >
> > > > > > > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
> > > > > >
> > > > > > Where do you get UEFI out of this?
> > > > >
> > > > > I assume it was UEFI as there was no discussion about this in U-Boot.
> > > > > Which firmware project was consulted about this?
> > > > >
> > > > > >
> > > > > > It is the discoverability of hardware that is fixed (and we are stuck
> > > > > > with). We can't change hardware. The disoverability may be PCI
> > > > > > VID/PID, USB device descriptors, or nothing. We only use DT when those
> > > > > > are not sufficient. For a software interface, there is no reason to
> > > > > > make them non-discoverable as the interface can be fixed (at least for
> > > > > > new things like FF-A).
> > > > >
> > > > > Here I am talking about the controller itself, the top-level node in
> > > > > the device tree. For PCI this is a device tree node and it should be
> > > > > the same here. So I am not saying that the devices on the bus need to
> > > > > be in the device tree (that can be optional, but may be useful in some
> > > > > situations where it is status and known).
> > > >
> > > > Sure, the PCI host bridges are not discoverable, have a bunch of
> > > > resources, and do need to be in DT. The downstream devices only do if
> > > > they have extra resources such as when a device is soldered down on a
> > > > board rather than a standard slot.
> > > >
> > > > > We need something like:
> > > > >
> > > > > ff-a {
> > > > >     compatible = "something";
> > > > > };
> > > > >
> > > > > I don't know what mechanism is actually used to communicate with it,
> > > > > but that will be enough to get the top-level driver started.
> > > >
> > > > There's discovery of FF-A itself and then discovery of FF-A features
> > > > (e.g. partitions). Both of those are discoverable without DT. The
> > > > first is done by checking the SMCCC version, then checking for FF-A
> > > > presence and features. Putting this into DT is redundant. Worse, what
> > > > if they disagree?
> > >
> > > Hi Simon,
> > >
> > > Do you agree with Rob, Ilias and myself that it makes more sense
> > > FF-A bus is discovered without a DT node and following the same approach as
> > > Linux ? (FF-A bus doesn't have a HW controller and is a purely SW bus,
> > > no configuration/description needed at DT level).
> > >
> > > Your suggestions are always welcome.
> >
> > I'm sorry I don't agree with that. It does need a compatible string,
> > like PCI has. You can just add it in U-Boot if Linux won't accept the
> > binding.
>
> It's not like PCI as the host side of PCI has non-discoverable resources.

OK I see. It is certainly an edge case.

>
> This all could have been designed better, but hindsight is 20/20 and
> things evolved step by step. There are a bunch of firmware services
> that are all behind SMCCC. The first (upstream) was PSCI. IIRC, SMCCC
> was invented a bit after that, but generalized PSCI for other
> services. Since then more have been added. More services get added one
> by one and yes we added bindings for them. Because what's one more...
> But that really needs to stop. We're stuck with h/w that's not
> discoverable, there's zero reason to do that with s/w interfaces. If
> we could redo everything, we'd have a node for SMCCC and that's it
> unless there's h/w resources provided to the rest of DT. But we can't,
> so SMCCC is discovered by the presence of PSCI.

I understand the background here, but if we don't take a stand on
this, this sort of thing will continue. Just because something works
in Linux does not mean that the binding (or lack of it) is good.

The reasons to do this are:
- avoids needing to manually call device_bind()
- avoids extra plumbing in U-Boot
- provides visibility into what is in the system, by looking at the
DT, like documentation
- DT is how devices are bound in U-Boot

You can see the problem if you look at ffa_device_get(). It is called
from ffa_bus_discover() which is a new addition into the board_init
list. We are trying to remove this list and certainly don't want new
things added!!

We don't need to change this in the Linux implementation, just add a
top-level DT node for U-Boot. I don't understand why that is such a
big problem?

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-12 23:43                                                             ` Simon Glass
@ 2023-01-13 10:44                                                               ` Abdellatif El Khlifi
  2023-01-13 18:00                                                                 ` Simon Glass
  2023-01-18  2:51                                                               ` Rob Herring
  1 sibling, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-01-13 10:44 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, nd, robh

On Thu, Jan 12, 2023 at 04:43:32PM -0700, Simon Glass wrote:
> Hi Rob,
> 
> On Wed, 11 Jan 2023 at 19:10, Rob Herring <robh@kernel.org> wrote:
> >
> > On Mon, Dec 19, 2022 at 1:21 PM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Abdellatif,
> > >
> > > On Mon, 19 Dec 2022 at 04:12, Abdellatif El Khlifi
> > > <abdellatif.elkhlifi@arm.com> wrote:
> > > >
> > > > On Mon, Dec 05, 2022 at 09:49:30AM -0600, Rob Herring wrote:
> > > > > On Sun, Dec 4, 2022 at 1:22 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > Hi Rob,
> > > > > >
> > > > > > On Tue, 29 Nov 2022 at 05:22, Rob Herring <robh@kernel.org> wrote:
> > > > > > >
> > > > > > > On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > > >
> > > > > > > > Hi Abdellatif,
> > > > > > > >
> > > > > > > > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > > > >
> > > > > > > > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > > > > > > > >  should be called 'priov' and should beHi Abdellatif,
> > > > > > > > > >
> > > > > > > >
> > > > > > > > [..]
> > > > > > > >
> > > > > > > > > > > +/**
> > > > > > > > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > > > > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > > > > > > > + *       successfully)
> > > > > > > > > > > + *
> > > > > > > > > > > + * This function makes sure the arm_ffa device is
> > > > > > > > > > > + * created, bound to this driver, probed and ready to use.
> > > > > > > > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > > > > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > > > > > > > + *
> > > > > > > > > > > + * Return:
> > > > > > > > > > > + *
> > > > > > > > > > > + * 0 on success. Otherwise, failure
> > > > > > > > > > > + */
> > > > > > > > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > > > > > > > +{
> > > > > > > > > > > +       int ret;
> > > > > > > > > > > +       struct udevice *dev = NULL;
> > > > > > > > > > > +
> > > > > > > > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > > > > > > > +                         &dev);
> > > > > > > > > >
> > > > > > > > > > Please add a DT binding. Even if only temporary, we need something for this.
> > > > > > > > >
> > > > > > > > > Thanks for the feedback. I'm happy to address all the comments.
> > > > > > > > >
> > > > > > > > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > > > > > > > about the following:
> > > > > > > > >
> > > > > > > > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > > > > > > > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > > > > > > > >   already applied in the FF-A kernel driver which comes with no DT support and
> > > > > > > > >   discovers the bus with bus_register() API [1].
> > > > > > > >
> > > > > > > > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
> > > > > > >
> > > > > > > Where do you get UEFI out of this?
> > > > > >
> > > > > > I assume it was UEFI as there was no discussion about this in U-Boot.
> > > > > > Which firmware project was consulted about this?
> > > > > >
> > > > > > >
> > > > > > > It is the discoverability of hardware that is fixed (and we are stuck
> > > > > > > with). We can't change hardware. The disoverability may be PCI
> > > > > > > VID/PID, USB device descriptors, or nothing. We only use DT when those
> > > > > > > are not sufficient. For a software interface, there is no reason to
> > > > > > > make them non-discoverable as the interface can be fixed (at least for
> > > > > > > new things like FF-A).
> > > > > >
> > > > > > Here I am talking about the controller itself, the top-level node in
> > > > > > the device tree. For PCI this is a device tree node and it should be
> > > > > > the same here. So I am not saying that the devices on the bus need to
> > > > > > be in the device tree (that can be optional, but may be useful in some
> > > > > > situations where it is status and known).
> > > > >
> > > > > Sure, the PCI host bridges are not discoverable, have a bunch of
> > > > > resources, and do need to be in DT. The downstream devices only do if
> > > > > they have extra resources such as when a device is soldered down on a
> > > > > board rather than a standard slot.
> > > > >
> > > > > > We need something like:
> > > > > >
> > > > > > ff-a {
> > > > > >     compatible = "something";
> > > > > > };
> > > > > >
> > > > > > I don't know what mechanism is actually used to communicate with it,
> > > > > > but that will be enough to get the top-level driver started.
> > > > >
> > > > > There's discovery of FF-A itself and then discovery of FF-A features
> > > > > (e.g. partitions). Both of those are discoverable without DT. The
> > > > > first is done by checking the SMCCC version, then checking for FF-A
> > > > > presence and features. Putting this into DT is redundant. Worse, what
> > > > > if they disagree?
> > > >
> > > > Hi Simon,
> > > >
> > > > Do you agree with Rob, Ilias and myself that it makes more sense
> > > > FF-A bus is discovered without a DT node and following the same approach as
> > > > Linux ? (FF-A bus doesn't have a HW controller and is a purely SW bus,
> > > > no configuration/description needed at DT level).
> > > >
> > > > Your suggestions are always welcome.
> > >
> > > I'm sorry I don't agree with that. It does need a compatible string,
> > > like PCI has. You can just add it in U-Boot if Linux won't accept the
> > > binding.
> >
> > It's not like PCI as the host side of PCI has non-discoverable resources.
> 
> OK I see. It is certainly an edge case.
> 
> >
> > This all could have been designed better, but hindsight is 20/20 and
> > things evolved step by step. There are a bunch of firmware services
> > that are all behind SMCCC. The first (upstream) was PSCI. IIRC, SMCCC
> > was invented a bit after that, but generalized PSCI for other
> > services. Since then more have been added. More services get added one
> > by one and yes we added bindings for them. Because what's one more...
> > But that really needs to stop. We're stuck with h/w that's not
> > discoverable, there's zero reason to do that with s/w interfaces. If
> > we could redo everything, we'd have a node for SMCCC and that's it
> > unless there's h/w resources provided to the rest of DT. But we can't,
> > so SMCCC is discovered by the presence of PSCI.
> 
> I understand the background here, but if we don't take a stand on
> this, this sort of thing will continue. Just because something works
> in Linux does not mean that the binding (or lack of it) is good.
> 
> The reasons to do this are:
> - avoids needing to manually call device_bind()
> - avoids extra plumbing in U-Boot
> - provides visibility into what is in the system, by looking at the
> DT, like documentation
> - DT is how devices are bound in U-Boot
> 
> You can see the problem if you look at ffa_device_get(). It is called
> from ffa_bus_discover() which is a new addition into the board_init
> list. We are trying to remove this list and certainly don't want new
> things added!!

Hi Simon,

As stated in the v8 patchset cover letter [1] and readme [2], the FF-A bus is discoverable on demand at runtime.

Clients (such as EFI) can discover the FF-A bus using ffa_bus_discover() API which triggers the
discovery process.

We no longer use the board_init list to discover the FF-A bus.

Please refer to the v8 patchset for the review.

Cheers

[1]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20221122131751.22747-4-abdellatif.elkhlifi@arm.com/#Z31doc:arch:arm64.ffa.rst

> 
> We don't need to change this in the Linux implementation, just add a
> top-level DT node for U-Boot. I don't understand why that is such a
> big problem?
> 
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-13 10:44                                                               ` Abdellatif El Khlifi
@ 2023-01-13 18:00                                                                 ` Simon Glass
  2023-01-16 13:23                                                                   ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-01-13 18:00 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: u-boot, nd, robh

Hi Abdellatif,

On Fri, 13 Jan 2023 at 03:44, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> On Thu, Jan 12, 2023 at 04:43:32PM -0700, Simon Glass wrote:
> > Hi Rob,
> >
> > On Wed, 11 Jan 2023 at 19:10, Rob Herring <robh@kernel.org> wrote:
> > >
> > > On Mon, Dec 19, 2022 at 1:21 PM Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Abdellatif,
> > > >
> > > > On Mon, 19 Dec 2022 at 04:12, Abdellatif El Khlifi
> > > > <abdellatif.elkhlifi@arm.com> wrote:
> > > > >
> > > > > On Mon, Dec 05, 2022 at 09:49:30AM -0600, Rob Herring wrote:
> > > > > > On Sun, Dec 4, 2022 at 1:22 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > >
> > > > > > > Hi Rob,
> > > > > > >
> > > > > > > On Tue, 29 Nov 2022 at 05:22, Rob Herring <robh@kernel.org> wrote:
> > > > > > > >
> > > > > > > > On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > >
> > > > > > > > > Hi Abdellatif,
> > > > > > > > >
> > > > > > > > > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > > > > >
> > > > > > > > > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > > > > > > > > >  should be called 'priov' and should beHi Abdellatif,
> > > > > > > > > > >
> > > > > > > > >
> > > > > > > > > [..]
> > > > > > > > >
> > > > > > > > > > > > +/**
> > > > > > > > > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > > > > > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > > > > > > > > + *       successfully)
> > > > > > > > > > > > + *
> > > > > > > > > > > > + * This function makes sure the arm_ffa device is
> > > > > > > > > > > > + * created, bound to this driver, probed and ready to use.
> > > > > > > > > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > > > > > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > > > > > > > > + *
> > > > > > > > > > > > + * Return:
> > > > > > > > > > > > + *
> > > > > > > > > > > > + * 0 on success. Otherwise, failure
> > > > > > > > > > > > + */
> > > > > > > > > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > > > > > > > > +{
> > > > > > > > > > > > +       int ret;
> > > > > > > > > > > > +       struct udevice *dev = NULL;
> > > > > > > > > > > > +
> > > > > > > > > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > > > > > > > > +                         &dev);
> > > > > > > > > > >
> > > > > > > > > > > Please add a DT binding. Even if only temporary, we need something for this.
> > > > > > > > > >
> > > > > > > > > > Thanks for the feedback. I'm happy to address all the comments.
> > > > > > > > > >
> > > > > > > > > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > > > > > > > > about the following:
> > > > > > > > > >
> > > > > > > > > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > > > > > > > > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > > > > > > > > >   already applied in the FF-A kernel driver which comes with no DT support and
> > > > > > > > > >   discovers the bus with bus_register() API [1].
> > > > > > > > >
> > > > > > > > > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
> > > > > > > >
> > > > > > > > Where do you get UEFI out of this?
> > > > > > >
> > > > > > > I assume it was UEFI as there was no discussion about this in U-Boot.
> > > > > > > Which firmware project was consulted about this?
> > > > > > >
> > > > > > > >
> > > > > > > > It is the discoverability of hardware that is fixed (and we are stuck
> > > > > > > > with). We can't change hardware. The disoverability may be PCI
> > > > > > > > VID/PID, USB device descriptors, or nothing. We only use DT when those
> > > > > > > > are not sufficient. For a software interface, there is no reason to
> > > > > > > > make them non-discoverable as the interface can be fixed (at least for
> > > > > > > > new things like FF-A).
> > > > > > >
> > > > > > > Here I am talking about the controller itself, the top-level node in
> > > > > > > the device tree. For PCI this is a device tree node and it should be
> > > > > > > the same here. So I am not saying that the devices on the bus need to
> > > > > > > be in the device tree (that can be optional, but may be useful in some
> > > > > > > situations where it is status and known).
> > > > > >
> > > > > > Sure, the PCI host bridges are not discoverable, have a bunch of
> > > > > > resources, and do need to be in DT. The downstream devices only do if
> > > > > > they have extra resources such as when a device is soldered down on a
> > > > > > board rather than a standard slot.
> > > > > >
> > > > > > > We need something like:
> > > > > > >
> > > > > > > ff-a {
> > > > > > >     compatible = "something";
> > > > > > > };
> > > > > > >
> > > > > > > I don't know what mechanism is actually used to communicate with it,
> > > > > > > but that will be enough to get the top-level driver started.
> > > > > >
> > > > > > There's discovery of FF-A itself and then discovery of FF-A features
> > > > > > (e.g. partitions). Both of those are discoverable without DT. The
> > > > > > first is done by checking the SMCCC version, then checking for FF-A
> > > > > > presence and features. Putting this into DT is redundant. Worse, what
> > > > > > if they disagree?
> > > > >
> > > > > Hi Simon,
> > > > >
> > > > > Do you agree with Rob, Ilias and myself that it makes more sense
> > > > > FF-A bus is discovered without a DT node and following the same approach as
> > > > > Linux ? (FF-A bus doesn't have a HW controller and is a purely SW bus,
> > > > > no configuration/description needed at DT level).
> > > > >
> > > > > Your suggestions are always welcome.
> > > >
> > > > I'm sorry I don't agree with that. It does need a compatible string,
> > > > like PCI has. You can just add it in U-Boot if Linux won't accept the
> > > > binding.
> > >
> > > It's not like PCI as the host side of PCI has non-discoverable resources.
> >
> > OK I see. It is certainly an edge case.
> >
> > >
> > > This all could have been designed better, but hindsight is 20/20 and
> > > things evolved step by step. There are a bunch of firmware services
> > > that are all behind SMCCC. The first (upstream) was PSCI. IIRC, SMCCC
> > > was invented a bit after that, but generalized PSCI for other
> > > services. Since then more have been added. More services get added one
> > > by one and yes we added bindings for them. Because what's one more...
> > > But that really needs to stop. We're stuck with h/w that's not
> > > discoverable, there's zero reason to do that with s/w interfaces. If
> > > we could redo everything, we'd have a node for SMCCC and that's it
> > > unless there's h/w resources provided to the rest of DT. But we can't,
> > > so SMCCC is discovered by the presence of PSCI.
> >
> > I understand the background here, but if we don't take a stand on
> > this, this sort of thing will continue. Just because something works
> > in Linux does not mean that the binding (or lack of it) is good.
> >
> > The reasons to do this are:
> > - avoids needing to manually call device_bind()
> > - avoids extra plumbing in U-Boot
> > - provides visibility into what is in the system, by looking at the
> > DT, like documentation
> > - DT is how devices are bound in U-Boot
> >
> > You can see the problem if you look at ffa_device_get(). It is called
> > from ffa_bus_discover() which is a new addition into the board_init
> > list. We are trying to remove this list and certainly don't want new
> > things added!!
>
> Hi Simon,
>
> As stated in the v8 patchset cover letter [1] and readme [2], the FF-A bus is discoverable on demand at runtime.
>
> Clients (such as EFI) can discover the FF-A bus using ffa_bus_discover() API which triggers the
> discovery process.
>
> We no longer use the board_init list to discover the FF-A bus.

That's because you have moved it to the command - everything that
wants to use this has to call ffa_bus_discover()...!

>
> Please refer to the v8 patchset for the review.

It still needs a DT node and the binding needs to happen with driver
model. Please put that in. See also how the sandbox emulation is done
for I2C, SPI, USB, PCI and every other bus, with something in the DT.

We have dm_scan_other() which can pick up other buses but that is just
one function and we don't support multiple versions of it. We could
add that I suppose, but as I say, where does it end?

You can create a u-boot-ffa.dtsi file with the appropriate node and
include that in any board or SoC that uses this feature. Sandbox can
have its emulation node also. You will know that everything is good
when you can boot U-Boot, type 'dm tree' and see your device in there
without running any other commands.

Regards,
Simon



>
> Cheers
>
> [1]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
> [2]: https://lore.kernel.org/all/20221122131751.22747-4-abdellatif.elkhlifi@arm.com/#Z31doc:arch:arm64.ffa.rst
>
> >
> > We don't need to change this in the Linux implementation, just add a
> > top-level DT node for U-Boot. I don't understand why that is such a
> > big problem?
> >
> > Regards,
> > Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-13 18:00                                                                 ` Simon Glass
@ 2023-01-16 13:23                                                                   ` Abdellatif El Khlifi
  2023-01-17 14:04                                                                     ` Tom Rini
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-01-16 13:23 UTC (permalink / raw)
  To: trini; +Cc: u-boot, nd, ilias.apalodimas, robh, sjg

On Fri, Jan 13, 2023 at 11:00:28AM -0700, Simon Glass wrote:
> Hi Abdellatif,
> 
> On Fri, 13 Jan 2023 at 03:44, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > On Thu, Jan 12, 2023 at 04:43:32PM -0700, Simon Glass wrote:
> > > Hi Rob,
> > >
> > > On Wed, 11 Jan 2023 at 19:10, Rob Herring <robh@kernel.org> wrote:
> > > >
> > > > On Mon, Dec 19, 2022 at 1:21 PM Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > Hi Abdellatif,
> > > > >
> > > > > On Mon, 19 Dec 2022 at 04:12, Abdellatif El Khlifi
> > > > > <abdellatif.elkhlifi@arm.com> wrote:
> > > > > >
> > > > > > On Mon, Dec 05, 2022 at 09:49:30AM -0600, Rob Herring wrote:
> > > > > > > On Sun, Dec 4, 2022 at 1:22 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > > >
> > > > > > > > Hi Rob,
> > > > > > > >
> > > > > > > > On Tue, 29 Nov 2022 at 05:22, Rob Herring <robh@kernel.org> wrote:
> > > > > > > > >
> > > > > > > > > On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > > >
> > > > > > > > > > Hi Abdellatif,
> > > > > > > > > >
> > > > > > > > > > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > > > > > >
> > > > > > > > > > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > > > > > > > > > >  should be called 'priov' and should beHi Abdellatif,
> > > > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > [..]
> > > > > > > > > >
> > > > > > > > > > > > > +/**
> > > > > > > > > > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > > > > > > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > > > > > > > > > + *       successfully)
> > > > > > > > > > > > > + *
> > > > > > > > > > > > > + * This function makes sure the arm_ffa device is
> > > > > > > > > > > > > + * created, bound to this driver, probed and ready to use.
> > > > > > > > > > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > > > > > > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > > > > > > > > > + *
> > > > > > > > > > > > > + * Return:
> > > > > > > > > > > > > + *
> > > > > > > > > > > > > + * 0 on success. Otherwise, failure
> > > > > > > > > > > > > + */
> > > > > > > > > > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > > > > > > > > > +{
> > > > > > > > > > > > > +       int ret;
> > > > > > > > > > > > > +       struct udevice *dev = NULL;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > > > > > > > > > +                         &dev);
> > > > > > > > > > > >
> > > > > > > > > > > > Please add a DT binding. Even if only temporary, we need something for this.
> > > > > > > > > > >
> > > > > > > > > > > Thanks for the feedback. I'm happy to address all the comments.
> > > > > > > > > > >
> > > > > > > > > > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > > > > > > > > > about the following:
> > > > > > > > > > >
> > > > > > > > > > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > > > > > > > > > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > > > > > > > > > >   already applied in the FF-A kernel driver which comes with no DT support and
> > > > > > > > > > >   discovers the bus with bus_register() API [1].
> > > > > > > > > >
> > > > > > > > > > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
> > > > > > > > >
> > > > > > > > > Where do you get UEFI out of this?
> > > > > > > >
> > > > > > > > I assume it was UEFI as there was no discussion about this in U-Boot.
> > > > > > > > Which firmware project was consulted about this?
> > > > > > > >
> > > > > > > > >
> > > > > > > > > It is the discoverability of hardware that is fixed (and we are stuck
> > > > > > > > > with). We can't change hardware. The disoverability may be PCI
> > > > > > > > > VID/PID, USB device descriptors, or nothing. We only use DT when those
> > > > > > > > > are not sufficient. For a software interface, there is no reason to
> > > > > > > > > make them non-discoverable as the interface can be fixed (at least for
> > > > > > > > > new things like FF-A).
> > > > > > > >
> > > > > > > > Here I am talking about the controller itself, the top-level node in
> > > > > > > > the device tree. For PCI this is a device tree node and it should be
> > > > > > > > the same here. So I am not saying that the devices on the bus need to
> > > > > > > > be in the device tree (that can be optional, but may be useful in some
> > > > > > > > situations where it is status and known).
> > > > > > >
> > > > > > > Sure, the PCI host bridges are not discoverable, have a bunch of
> > > > > > > resources, and do need to be in DT. The downstream devices only do if
> > > > > > > they have extra resources such as when a device is soldered down on a
> > > > > > > board rather than a standard slot.
> > > > > > >
> > > > > > > > We need something like:
> > > > > > > >
> > > > > > > > ff-a {
> > > > > > > >     compatible = "something";
> > > > > > > > };
> > > > > > > >
> > > > > > > > I don't know what mechanism is actually used to communicate with it,
> > > > > > > > but that will be enough to get the top-level driver started.
> > > > > > >
> > > > > > > There's discovery of FF-A itself and then discovery of FF-A features
> > > > > > > (e.g. partitions). Both of those are discoverable without DT. The
> > > > > > > first is done by checking the SMCCC version, then checking for FF-A
> > > > > > > presence and features. Putting this into DT is redundant. Worse, what
> > > > > > > if they disagree?
> > > > > >
> > > > > > Hi Simon,
> > > > > >
> > > > > > Do you agree with Rob, Ilias and myself that it makes more sense
> > > > > > FF-A bus is discovered without a DT node and following the same approach as
> > > > > > Linux ? (FF-A bus doesn't have a HW controller and is a purely SW bus,
> > > > > > no configuration/description needed at DT level).
> > > > > >
> > > > > > Your suggestions are always welcome.
> > > > >
> > > > > I'm sorry I don't agree with that. It does need a compatible string,
> > > > > like PCI has. You can just add it in U-Boot if Linux won't accept the
> > > > > binding.
> > > >
> > > > It's not like PCI as the host side of PCI has non-discoverable resources.
> > >
> > > OK I see. It is certainly an edge case.
> > >
> > > >
> > > > This all could have been designed better, but hindsight is 20/20 and
> > > > things evolved step by step. There are a bunch of firmware services
> > > > that are all behind SMCCC. The first (upstream) was PSCI. IIRC, SMCCC
> > > > was invented a bit after that, but generalized PSCI for other
> > > > services. Since then more have been added. More services get added one
> > > > by one and yes we added bindings for them. Because what's one more...
> > > > But that really needs to stop. We're stuck with h/w that's not
> > > > discoverable, there's zero reason to do that with s/w interfaces. If
> > > > we could redo everything, we'd have a node for SMCCC and that's it
> > > > unless there's h/w resources provided to the rest of DT. But we can't,
> > > > so SMCCC is discovered by the presence of PSCI.
> > >
> > > I understand the background here, but if we don't take a stand on
> > > this, this sort of thing will continue. Just because something works
> > > in Linux does not mean that the binding (or lack of it) is good.
> > >
> > > The reasons to do this are:
> > > - avoids needing to manually call device_bind()
> > > - avoids extra plumbing in U-Boot
> > > - provides visibility into what is in the system, by looking at the
> > > DT, like documentation
> > > - DT is how devices are bound in U-Boot
> > >
> > > You can see the problem if you look at ffa_device_get(). It is called
> > > from ffa_bus_discover() which is a new addition into the board_init
> > > list. We are trying to remove this list and certainly don't want new
> > > things added!!
> >
> > Hi Simon,
> >
> > As stated in the v8 patchset cover letter [1] and readme [2], the FF-A bus is discoverable on demand at runtime.
> >
> > Clients (such as EFI) can discover the FF-A bus using ffa_bus_discover() API which triggers the
> > discovery process.
> >
> > We no longer use the board_init list to discover the FF-A bus.
> 
> That's because you have moved it to the command - everything that
> wants to use this has to call ffa_bus_discover()...!
> 
> >
> > Please refer to the v8 patchset for the review.
> 
> It still needs a DT node and the binding needs to happen with driver
> model. Please put that in. See also how the sandbox emulation is done
> for I2C, SPI, USB, PCI and every other bus, with something in the DT.
> 
> We have dm_scan_other() which can pick up other buses but that is just
> one function and we don't support multiple versions of it. We could
> add that I suppose, but as I say, where does it end?
> 
> You can create a u-boot-ffa.dtsi file with the appropriate node and
> include that in any board or SoC that uses this feature. Sandbox can
> have its emulation node also. You will know that everything is good
> when you can boot U-Boot, type 'dm tree' and see your device in there
> without running any other commands.

Hi Tom,

Any thoughts about this topic ? (discovering FF-A bus manually like done
in Linux without DT node vs using a DT node)

Cheers

> 
> Regards,
> Simon
> 
> 
> 
> >
> > Cheers
> >
> > [1]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
> > [2]: https://lore.kernel.org/all/20221122131751.22747-4-abdellatif.elkhlifi@arm.com/#Z31doc:arch:arm64.ffa.rst
> >
> > >
> > > We don't need to change this in the Linux implementation, just add a
> > > top-level DT node for U-Boot. I don't understand why that is such a
> > > big problem?
> > >
> > > Regards,
> > > Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-16 13:23                                                                   ` Abdellatif El Khlifi
@ 2023-01-17 14:04                                                                     ` Tom Rini
  2023-01-18  3:18                                                                       ` Rob Herring
  0 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-01-17 14:04 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: u-boot, nd, ilias.apalodimas, robh, sjg

[-- Attachment #1: Type: text/plain, Size: 10893 bytes --]

On Mon, Jan 16, 2023 at 01:23:53PM +0000, Abdellatif El Khlifi wrote:
> On Fri, Jan 13, 2023 at 11:00:28AM -0700, Simon Glass wrote:
> > Hi Abdellatif,
> > 
> > On Fri, 13 Jan 2023 at 03:44, Abdellatif El Khlifi
> > <abdellatif.elkhlifi@arm.com> wrote:
> > >
> > > On Thu, Jan 12, 2023 at 04:43:32PM -0700, Simon Glass wrote:
> > > > Hi Rob,
> > > >
> > > > On Wed, 11 Jan 2023 at 19:10, Rob Herring <robh@kernel.org> wrote:
> > > > >
> > > > > On Mon, Dec 19, 2022 at 1:21 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > Hi Abdellatif,
> > > > > >
> > > > > > On Mon, 19 Dec 2022 at 04:12, Abdellatif El Khlifi
> > > > > > <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > >
> > > > > > > On Mon, Dec 05, 2022 at 09:49:30AM -0600, Rob Herring wrote:
> > > > > > > > On Sun, Dec 4, 2022 at 1:22 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > >
> > > > > > > > > Hi Rob,
> > > > > > > > >
> > > > > > > > > On Tue, 29 Nov 2022 at 05:22, Rob Herring <robh@kernel.org> wrote:
> > > > > > > > > >
> > > > > > > > > > On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > > > >
> > > > > > > > > > > Hi Abdellatif,
> > > > > > > > > > >
> > > > > > > > > > > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > > > > > > > > > > >  should be called 'priov' and should beHi Abdellatif,
> > > > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > [..]
> > > > > > > > > > >
> > > > > > > > > > > > > > +/**
> > > > > > > > > > > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > > > > > > > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > > > > > > > > > > + *       successfully)
> > > > > > > > > > > > > > + *
> > > > > > > > > > > > > > + * This function makes sure the arm_ffa device is
> > > > > > > > > > > > > > + * created, bound to this driver, probed and ready to use.
> > > > > > > > > > > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > > > > > > > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > > > > > > > > > > + *
> > > > > > > > > > > > > > + * Return:
> > > > > > > > > > > > > > + *
> > > > > > > > > > > > > > + * 0 on success. Otherwise, failure
> > > > > > > > > > > > > > + */
> > > > > > > > > > > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > > > > > > > > > > +{
> > > > > > > > > > > > > > +       int ret;
> > > > > > > > > > > > > > +       struct udevice *dev = NULL;
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > > > > > > > > > > +                         &dev);
> > > > > > > > > > > > >
> > > > > > > > > > > > > Please add a DT binding. Even if only temporary, we need something for this.
> > > > > > > > > > > >
> > > > > > > > > > > > Thanks for the feedback. I'm happy to address all the comments.
> > > > > > > > > > > >
> > > > > > > > > > > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > > > > > > > > > > about the following:
> > > > > > > > > > > >
> > > > > > > > > > > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > > > > > > > > > > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > > > > > > > > > > >   already applied in the FF-A kernel driver which comes with no DT support and
> > > > > > > > > > > >   discovers the bus with bus_register() API [1].
> > > > > > > > > > >
> > > > > > > > > > > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
> > > > > > > > > >
> > > > > > > > > > Where do you get UEFI out of this?
> > > > > > > > >
> > > > > > > > > I assume it was UEFI as there was no discussion about this in U-Boot.
> > > > > > > > > Which firmware project was consulted about this?
> > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > It is the discoverability of hardware that is fixed (and we are stuck
> > > > > > > > > > with). We can't change hardware. The disoverability may be PCI
> > > > > > > > > > VID/PID, USB device descriptors, or nothing. We only use DT when those
> > > > > > > > > > are not sufficient. For a software interface, there is no reason to
> > > > > > > > > > make them non-discoverable as the interface can be fixed (at least for
> > > > > > > > > > new things like FF-A).
> > > > > > > > >
> > > > > > > > > Here I am talking about the controller itself, the top-level node in
> > > > > > > > > the device tree. For PCI this is a device tree node and it should be
> > > > > > > > > the same here. So I am not saying that the devices on the bus need to
> > > > > > > > > be in the device tree (that can be optional, but may be useful in some
> > > > > > > > > situations where it is status and known).
> > > > > > > >
> > > > > > > > Sure, the PCI host bridges are not discoverable, have a bunch of
> > > > > > > > resources, and do need to be in DT. The downstream devices only do if
> > > > > > > > they have extra resources such as when a device is soldered down on a
> > > > > > > > board rather than a standard slot.
> > > > > > > >
> > > > > > > > > We need something like:
> > > > > > > > >
> > > > > > > > > ff-a {
> > > > > > > > >     compatible = "something";
> > > > > > > > > };
> > > > > > > > >
> > > > > > > > > I don't know what mechanism is actually used to communicate with it,
> > > > > > > > > but that will be enough to get the top-level driver started.
> > > > > > > >
> > > > > > > > There's discovery of FF-A itself and then discovery of FF-A features
> > > > > > > > (e.g. partitions). Both of those are discoverable without DT. The
> > > > > > > > first is done by checking the SMCCC version, then checking for FF-A
> > > > > > > > presence and features. Putting this into DT is redundant. Worse, what
> > > > > > > > if they disagree?
> > > > > > >
> > > > > > > Hi Simon,
> > > > > > >
> > > > > > > Do you agree with Rob, Ilias and myself that it makes more sense
> > > > > > > FF-A bus is discovered without a DT node and following the same approach as
> > > > > > > Linux ? (FF-A bus doesn't have a HW controller and is a purely SW bus,
> > > > > > > no configuration/description needed at DT level).
> > > > > > >
> > > > > > > Your suggestions are always welcome.
> > > > > >
> > > > > > I'm sorry I don't agree with that. It does need a compatible string,
> > > > > > like PCI has. You can just add it in U-Boot if Linux won't accept the
> > > > > > binding.
> > > > >
> > > > > It's not like PCI as the host side of PCI has non-discoverable resources.
> > > >
> > > > OK I see. It is certainly an edge case.
> > > >
> > > > >
> > > > > This all could have been designed better, but hindsight is 20/20 and
> > > > > things evolved step by step. There are a bunch of firmware services
> > > > > that are all behind SMCCC. The first (upstream) was PSCI. IIRC, SMCCC
> > > > > was invented a bit after that, but generalized PSCI for other
> > > > > services. Since then more have been added. More services get added one
> > > > > by one and yes we added bindings for them. Because what's one more...
> > > > > But that really needs to stop. We're stuck with h/w that's not
> > > > > discoverable, there's zero reason to do that with s/w interfaces. If
> > > > > we could redo everything, we'd have a node for SMCCC and that's it
> > > > > unless there's h/w resources provided to the rest of DT. But we can't,
> > > > > so SMCCC is discovered by the presence of PSCI.
> > > >
> > > > I understand the background here, but if we don't take a stand on
> > > > this, this sort of thing will continue. Just because something works
> > > > in Linux does not mean that the binding (or lack of it) is good.
> > > >
> > > > The reasons to do this are:
> > > > - avoids needing to manually call device_bind()
> > > > - avoids extra plumbing in U-Boot
> > > > - provides visibility into what is in the system, by looking at the
> > > > DT, like documentation
> > > > - DT is how devices are bound in U-Boot
> > > >
> > > > You can see the problem if you look at ffa_device_get(). It is called
> > > > from ffa_bus_discover() which is a new addition into the board_init
> > > > list. We are trying to remove this list and certainly don't want new
> > > > things added!!
> > >
> > > Hi Simon,
> > >
> > > As stated in the v8 patchset cover letter [1] and readme [2], the FF-A bus is discoverable on demand at runtime.
> > >
> > > Clients (such as EFI) can discover the FF-A bus using ffa_bus_discover() API which triggers the
> > > discovery process.
> > >
> > > We no longer use the board_init list to discover the FF-A bus.
> > 
> > That's because you have moved it to the command - everything that
> > wants to use this has to call ffa_bus_discover()...!
> > 
> > >
> > > Please refer to the v8 patchset for the review.
> > 
> > It still needs a DT node and the binding needs to happen with driver
> > model. Please put that in. See also how the sandbox emulation is done
> > for I2C, SPI, USB, PCI and every other bus, with something in the DT.
> > 
> > We have dm_scan_other() which can pick up other buses but that is just
> > one function and we don't support multiple versions of it. We could
> > add that I suppose, but as I say, where does it end?
> > 
> > You can create a u-boot-ffa.dtsi file with the appropriate node and
> > include that in any board or SoC that uses this feature. Sandbox can
> > have its emulation node also. You will know that everything is good
> > when you can boot U-Boot, type 'dm tree' and see your device in there
> > without running any other commands.
> 
> Hi Tom,
> 
> Any thoughts about this topic ? (discovering FF-A bus manually like done
> in Linux without DT node vs using a DT node)

Yes, I think Simon's point is right. Without a DT node, it's a bunch of
one-off special code to discover something that we could get from just
having a node. If you want to avoid doing this, you need to show
- the patchset, using a DT node
- the patchset, without using a DT node, but instead something that
  addresses Simon's feedback.

And then demonstrate that the 2nd approach is cleaner than the first.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-12 23:43                                                             ` Simon Glass
  2023-01-13 10:44                                                               ` Abdellatif El Khlifi
@ 2023-01-18  2:51                                                               ` Rob Herring
  2023-01-18 12:49                                                                 ` Tom Rini
  1 sibling, 1 reply; 478+ messages in thread
From: Rob Herring @ 2023-01-18  2:51 UTC (permalink / raw)
  To: Simon Glass
  Cc: Abdellatif El Khlifi, ilias.apalodimas, jens.wiklander,
	achin.gupta, trini, xueliang.zhong, nd, u-boot

On Thu, Jan 12, 2023 at 5:43 PM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Rob,
>
> On Wed, 11 Jan 2023 at 19:10, Rob Herring <robh@kernel.org> wrote:
> >
> > On Mon, Dec 19, 2022 at 1:21 PM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Abdellatif,
> > >
> > > On Mon, 19 Dec 2022 at 04:12, Abdellatif El Khlifi
> > > <abdellatif.elkhlifi@arm.com> wrote:
> > > >
> > > > On Mon, Dec 05, 2022 at 09:49:30AM -0600, Rob Herring wrote:
> > > > > On Sun, Dec 4, 2022 at 1:22 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > Hi Rob,
> > > > > >
> > > > > > On Tue, 29 Nov 2022 at 05:22, Rob Herring <robh@kernel.org> wrote:
> > > > > > >
> > > > > > > On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > > >
> > > > > > > > Hi Abdellatif,
> > > > > > > >
> > > > > > > > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > > > >
> > > > > > > > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > > > > > > > >  should be called 'priov' and should beHi Abdellatif,
> > > > > > > > > >
> > > > > > > >
> > > > > > > > [..]
> > > > > > > >
> > > > > > > > > > > +/**
> > > > > > > > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > > > > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > > > > > > > + *       successfully)
> > > > > > > > > > > + *
> > > > > > > > > > > + * This function makes sure the arm_ffa device is
> > > > > > > > > > > + * created, bound to this driver, probed and ready to use.
> > > > > > > > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > > > > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > > > > > > > + *
> > > > > > > > > > > + * Return:
> > > > > > > > > > > + *
> > > > > > > > > > > + * 0 on success. Otherwise, failure
> > > > > > > > > > > + */
> > > > > > > > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > > > > > > > +{
> > > > > > > > > > > +       int ret;
> > > > > > > > > > > +       struct udevice *dev = NULL;
> > > > > > > > > > > +
> > > > > > > > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > > > > > > > +                         &dev);
> > > > > > > > > >
> > > > > > > > > > Please add a DT binding. Even if only temporary, we need something for this.
> > > > > > > > >
> > > > > > > > > Thanks for the feedback. I'm happy to address all the comments.
> > > > > > > > >
> > > > > > > > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > > > > > > > about the following:
> > > > > > > > >
> > > > > > > > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > > > > > > > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > > > > > > > >   already applied in the FF-A kernel driver which comes with no DT support and
> > > > > > > > >   discovers the bus with bus_register() API [1].
> > > > > > > >
> > > > > > > > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
> > > > > > >
> > > > > > > Where do you get UEFI out of this?
> > > > > >
> > > > > > I assume it was UEFI as there was no discussion about this in U-Boot.
> > > > > > Which firmware project was consulted about this?
> > > > > >
> > > > > > >
> > > > > > > It is the discoverability of hardware that is fixed (and we are stuck
> > > > > > > with). We can't change hardware. The disoverability may be PCI
> > > > > > > VID/PID, USB device descriptors, or nothing. We only use DT when those
> > > > > > > are not sufficient. For a software interface, there is no reason to
> > > > > > > make them non-discoverable as the interface can be fixed (at least for
> > > > > > > new things like FF-A).
> > > > > >
> > > > > > Here I am talking about the controller itself, the top-level node in
> > > > > > the device tree. For PCI this is a device tree node and it should be
> > > > > > the same here. So I am not saying that the devices on the bus need to
> > > > > > be in the device tree (that can be optional, but may be useful in some
> > > > > > situations where it is status and known).
> > > > >
> > > > > Sure, the PCI host bridges are not discoverable, have a bunch of
> > > > > resources, and do need to be in DT. The downstream devices only do if
> > > > > they have extra resources such as when a device is soldered down on a
> > > > > board rather than a standard slot.
> > > > >
> > > > > > We need something like:
> > > > > >
> > > > > > ff-a {
> > > > > >     compatible = "something";
> > > > > > };
> > > > > >
> > > > > > I don't know what mechanism is actually used to communicate with it,
> > > > > > but that will be enough to get the top-level driver started.
> > > > >
> > > > > There's discovery of FF-A itself and then discovery of FF-A features
> > > > > (e.g. partitions). Both of those are discoverable without DT. The
> > > > > first is done by checking the SMCCC version, then checking for FF-A
> > > > > presence and features. Putting this into DT is redundant. Worse, what
> > > > > if they disagree?
> > > >
> > > > Hi Simon,
> > > >
> > > > Do you agree with Rob, Ilias and myself that it makes more sense
> > > > FF-A bus is discovered without a DT node and following the same approach as
> > > > Linux ? (FF-A bus doesn't have a HW controller and is a purely SW bus,
> > > > no configuration/description needed at DT level).
> > > >
> > > > Your suggestions are always welcome.
> > >
> > > I'm sorry I don't agree with that. It does need a compatible string,
> > > like PCI has. You can just add it in U-Boot if Linux won't accept the
> > > binding.
> >
> > It's not like PCI as the host side of PCI has non-discoverable resources.
>
> OK I see. It is certainly an edge case.
>
> >
> > This all could have been designed better, but hindsight is 20/20 and
> > things evolved step by step. There are a bunch of firmware services
> > that are all behind SMCCC. The first (upstream) was PSCI. IIRC, SMCCC
> > was invented a bit after that, but generalized PSCI for other
> > services. Since then more have been added. More services get added one
> > by one and yes we added bindings for them. Because what's one more...
> > But that really needs to stop. We're stuck with h/w that's not
> > discoverable, there's zero reason to do that with s/w interfaces. If
> > we could redo everything, we'd have a node for SMCCC and that's it
> > unless there's h/w resources provided to the rest of DT. But we can't,
> > so SMCCC is discovered by the presence of PSCI.
>
> I understand the background here, but if we don't take a stand on
> this, this sort of thing will continue.

I agree completely (but I think what you mean for 'this' is
different). Using DT for s/w features has to stop.

Every new SMCCC firmware interface we get a new binding for it. FF-A
originally had a bunch of crap in the binding. So did Op-tee. Why does
each new firmware feature need a DT node? As software people, can't we
design software interfaces which are discoverable on their own rather
than using a hardware description for discovering them? The only part
we can't discover is whether we have SMCCC or not, but we already have
that in DT with the PSCI node because if we have PSCI, we have SMCCC.

It is the same problem with that UEFI SPI protocol binding on the list
last week.

> Just because something works
> in Linux does not mean that the binding (or lack of it) is good.
>
> The reasons to do this are:
> - avoids needing to manually call device_bind()
> - avoids extra plumbing in U-Boot
> - provides visibility into what is in the system, by looking at the
> DT, like documentation
> - DT is how devices are bound in U-Boot
>
> You can see the problem if you look at ffa_device_get(). It is called
> from ffa_bus_discover() which is a new addition into the board_init
> list. We are trying to remove this list and certainly don't want new
> things added!!

That seems less than ideal. How do you init PSCI? Or u-boot doesn't
touch it? The low-level code for both should be shared if not already.

> We don't need to change this in the Linux implementation, just add a
> top-level DT node for U-Boot. I don't understand why that is such a
> big problem?

It's a line in the sand. Yeah, 1 compatible is not a big deal, but
then it is an invitation to add to the binding and add a compatible
for the next SMCCC firmware feature.

Rob

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-17 14:04                                                                     ` Tom Rini
@ 2023-01-18  3:18                                                                       ` Rob Herring
  0 siblings, 0 replies; 478+ messages in thread
From: Rob Herring @ 2023-01-18  3:18 UTC (permalink / raw)
  To: Tom Rini; +Cc: Abdellatif El Khlifi, u-boot, nd, ilias.apalodimas, sjg

On Tue, Jan 17, 2023 at 8:04 AM Tom Rini <trini@konsulko.com> wrote:
>
> On Mon, Jan 16, 2023 at 01:23:53PM +0000, Abdellatif El Khlifi wrote:
> > On Fri, Jan 13, 2023 at 11:00:28AM -0700, Simon Glass wrote:
> > > Hi Abdellatif,
> > >
> > > On Fri, 13 Jan 2023 at 03:44, Abdellatif El Khlifi
> > > <abdellatif.elkhlifi@arm.com> wrote:
> > > >
> > > > On Thu, Jan 12, 2023 at 04:43:32PM -0700, Simon Glass wrote:
> > > > > Hi Rob,
> > > > >
> > > > > On Wed, 11 Jan 2023 at 19:10, Rob Herring <robh@kernel.org> wrote:
> > > > > >
> > > > > > On Mon, Dec 19, 2022 at 1:21 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > >
> > > > > > > Hi Abdellatif,
> > > > > > >
> > > > > > > On Mon, 19 Dec 2022 at 04:12, Abdellatif El Khlifi
> > > > > > > <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > > >
> > > > > > > > On Mon, Dec 05, 2022 at 09:49:30AM -0600, Rob Herring wrote:
> > > > > > > > > On Sun, Dec 4, 2022 at 1:22 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > > >
> > > > > > > > > > Hi Rob,
> > > > > > > > > >
> > > > > > > > > > On Tue, 29 Nov 2022 at 05:22, Rob Herring <robh@kernel.org> wrote:
> > > > > > > > > > >
> > > > > > > > > > > On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > Hi Abdellatif,
> > > > > > > > > > > >
> > > > > > > > > > > > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > > > > > > > >
> > > > > > > > > > > > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > > > > > > > > > > > >  should be called 'priov' and should beHi Abdellatif,
> > > > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > > [..]
> > > > > > > > > > > >
> > > > > > > > > > > > > > > +/**
> > > > > > > > > > > > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > > > > > > > > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > > > > > > > > > > > + *       successfully)
> > > > > > > > > > > > > > > + *
> > > > > > > > > > > > > > > + * This function makes sure the arm_ffa device is
> > > > > > > > > > > > > > > + * created, bound to this driver, probed and ready to use.
> > > > > > > > > > > > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > > > > > > > > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > > > > > > > > > > > + *
> > > > > > > > > > > > > > > + * Return:
> > > > > > > > > > > > > > > + *
> > > > > > > > > > > > > > > + * 0 on success. Otherwise, failure
> > > > > > > > > > > > > > > + */
> > > > > > > > > > > > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > > > > > > > > > > > +{
> > > > > > > > > > > > > > > +       int ret;
> > > > > > > > > > > > > > > +       struct udevice *dev = NULL;
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > > > > > > > > > > > +                         &dev);
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > Please add a DT binding. Even if only temporary, we need something for this.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Thanks for the feedback. I'm happy to address all the comments.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > > > > > > > > > > > about the following:
> > > > > > > > > > > > >
> > > > > > > > > > > > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > > > > > > > > > > > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > > > > > > > > > > > >   already applied in the FF-A kernel driver which comes with no DT support and
> > > > > > > > > > > > >   discovers the bus with bus_register() API [1].
> > > > > > > > > > > >
> > > > > > > > > > > > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
> > > > > > > > > > >
> > > > > > > > > > > Where do you get UEFI out of this?
> > > > > > > > > >
> > > > > > > > > > I assume it was UEFI as there was no discussion about this in U-Boot.
> > > > > > > > > > Which firmware project was consulted about this?
> > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > It is the discoverability of hardware that is fixed (and we are stuck
> > > > > > > > > > > with). We can't change hardware. The disoverability may be PCI
> > > > > > > > > > > VID/PID, USB device descriptors, or nothing. We only use DT when those
> > > > > > > > > > > are not sufficient. For a software interface, there is no reason to
> > > > > > > > > > > make them non-discoverable as the interface can be fixed (at least for
> > > > > > > > > > > new things like FF-A).
> > > > > > > > > >
> > > > > > > > > > Here I am talking about the controller itself, the top-level node in
> > > > > > > > > > the device tree. For PCI this is a device tree node and it should be
> > > > > > > > > > the same here. So I am not saying that the devices on the bus need to
> > > > > > > > > > be in the device tree (that can be optional, but may be useful in some
> > > > > > > > > > situations where it is status and known).
> > > > > > > > >
> > > > > > > > > Sure, the PCI host bridges are not discoverable, have a bunch of
> > > > > > > > > resources, and do need to be in DT. The downstream devices only do if
> > > > > > > > > they have extra resources such as when a device is soldered down on a
> > > > > > > > > board rather than a standard slot.
> > > > > > > > >
> > > > > > > > > > We need something like:
> > > > > > > > > >
> > > > > > > > > > ff-a {
> > > > > > > > > >     compatible = "something";
> > > > > > > > > > };
> > > > > > > > > >
> > > > > > > > > > I don't know what mechanism is actually used to communicate with it,
> > > > > > > > > > but that will be enough to get the top-level driver started.
> > > > > > > > >
> > > > > > > > > There's discovery of FF-A itself and then discovery of FF-A features
> > > > > > > > > (e.g. partitions). Both of those are discoverable without DT. The
> > > > > > > > > first is done by checking the SMCCC version, then checking for FF-A
> > > > > > > > > presence and features. Putting this into DT is redundant. Worse, what
> > > > > > > > > if they disagree?
> > > > > > > >
> > > > > > > > Hi Simon,
> > > > > > > >
> > > > > > > > Do you agree with Rob, Ilias and myself that it makes more sense
> > > > > > > > FF-A bus is discovered without a DT node and following the same approach as
> > > > > > > > Linux ? (FF-A bus doesn't have a HW controller and is a purely SW bus,
> > > > > > > > no configuration/description needed at DT level).
> > > > > > > >
> > > > > > > > Your suggestions are always welcome.
> > > > > > >
> > > > > > > I'm sorry I don't agree with that. It does need a compatible string,
> > > > > > > like PCI has. You can just add it in U-Boot if Linux won't accept the
> > > > > > > binding.
> > > > > >
> > > > > > It's not like PCI as the host side of PCI has non-discoverable resources.
> > > > >
> > > > > OK I see. It is certainly an edge case.
> > > > >
> > > > > >
> > > > > > This all could have been designed better, but hindsight is 20/20 and
> > > > > > things evolved step by step. There are a bunch of firmware services
> > > > > > that are all behind SMCCC. The first (upstream) was PSCI. IIRC, SMCCC
> > > > > > was invented a bit after that, but generalized PSCI for other
> > > > > > services. Since then more have been added. More services get added one
> > > > > > by one and yes we added bindings for them. Because what's one more...
> > > > > > But that really needs to stop. We're stuck with h/w that's not
> > > > > > discoverable, there's zero reason to do that with s/w interfaces. If
> > > > > > we could redo everything, we'd have a node for SMCCC and that's it
> > > > > > unless there's h/w resources provided to the rest of DT. But we can't,
> > > > > > so SMCCC is discovered by the presence of PSCI.
> > > > >
> > > > > I understand the background here, but if we don't take a stand on
> > > > > this, this sort of thing will continue. Just because something works
> > > > > in Linux does not mean that the binding (or lack of it) is good.
> > > > >
> > > > > The reasons to do this are:
> > > > > - avoids needing to manually call device_bind()
> > > > > - avoids extra plumbing in U-Boot
> > > > > - provides visibility into what is in the system, by looking at the
> > > > > DT, like documentation
> > > > > - DT is how devices are bound in U-Boot
> > > > >
> > > > > You can see the problem if you look at ffa_device_get(). It is called
> > > > > from ffa_bus_discover() which is a new addition into the board_init
> > > > > list. We are trying to remove this list and certainly don't want new
> > > > > things added!!
> > > >
> > > > Hi Simon,
> > > >
> > > > As stated in the v8 patchset cover letter [1] and readme [2], the FF-A bus is discoverable on demand at runtime.
> > > >
> > > > Clients (such as EFI) can discover the FF-A bus using ffa_bus_discover() API which triggers the
> > > > discovery process.
> > > >
> > > > We no longer use the board_init list to discover the FF-A bus.
> > >
> > > That's because you have moved it to the command - everything that
> > > wants to use this has to call ffa_bus_discover()...!
> > >
> > > >
> > > > Please refer to the v8 patchset for the review.
> > >
> > > It still needs a DT node and the binding needs to happen with driver
> > > model. Please put that in. See also how the sandbox emulation is done
> > > for I2C, SPI, USB, PCI and every other bus, with something in the DT.
> > >
> > > We have dm_scan_other() which can pick up other buses but that is just
> > > one function and we don't support multiple versions of it. We could
> > > add that I suppose, but as I say, where does it end?
> > >
> > > You can create a u-boot-ffa.dtsi file with the appropriate node and
> > > include that in any board or SoC that uses this feature. Sandbox can
> > > have its emulation node also. You will know that everything is good
> > > when you can boot U-Boot, type 'dm tree' and see your device in there
> > > without running any other commands.
> >
> > Hi Tom,
> >
> > Any thoughts about this topic ? (discovering FF-A bus manually like done
> > in Linux without DT node vs using a DT node)
>
> Yes, I think Simon's point is right. Without a DT node, it's a bunch of
> one-off special code to discover something that we could get from just
> having a node.

DT simply is not always a nice 1:1 with what the client wants for
drivers. It's not an abstraction layer for the OS. I see it tried All
The Time. We have the same problem on things like CPUFreq because
there is often not a h/w block, but a scattered collection of bits of
h/w the driver has to control and still needs platform specific
knowledge.

> If you want to avoid doing this, you need to show
> - the patchset, using a DT node

That would be the PSCI driver which has a node.

> - the patchset, without using a DT node, but instead something that
>   addresses Simon's feedback.

That would be the SMCCC TRNG driver which has no node.

Perhaps if there was an 'SMCCC bus' which PSCI, TRNG, FF-A, etc. all
sat on, then that bus code can discover every sub-function and create
devices for them. Not sure, I'm not really familiar with the current
DM stuff.

Rob

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-18  2:51                                                               ` Rob Herring
@ 2023-01-18 12:49                                                                 ` Tom Rini
  2023-01-18 13:46                                                                   ` Sudeep Holla
  0 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-01-18 12:49 UTC (permalink / raw)
  To: Rob Herring
  Cc: Simon Glass, Abdellatif El Khlifi, ilias.apalodimas,
	jens.wiklander, achin.gupta, xueliang.zhong, nd, u-boot

[-- Attachment #1: Type: text/plain, Size: 10350 bytes --]

On Tue, Jan 17, 2023 at 08:51:51PM -0600, Rob Herring wrote:
> On Thu, Jan 12, 2023 at 5:43 PM Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Rob,
> >
> > On Wed, 11 Jan 2023 at 19:10, Rob Herring <robh@kernel.org> wrote:
> > >
> > > On Mon, Dec 19, 2022 at 1:21 PM Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Abdellatif,
> > > >
> > > > On Mon, 19 Dec 2022 at 04:12, Abdellatif El Khlifi
> > > > <abdellatif.elkhlifi@arm.com> wrote:
> > > > >
> > > > > On Mon, Dec 05, 2022 at 09:49:30AM -0600, Rob Herring wrote:
> > > > > > On Sun, Dec 4, 2022 at 1:22 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > >
> > > > > > > Hi Rob,
> > > > > > >
> > > > > > > On Tue, 29 Nov 2022 at 05:22, Rob Herring <robh@kernel.org> wrote:
> > > > > > > >
> > > > > > > > On Fri, Nov 25, 2022 at 3:18 PM Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > >
> > > > > > > > > Hi Abdellatif,
> > > > > > > > >
> > > > > > > > > On Thu, 24 Nov 2022 at 06:21, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > > > > >
> > > > > > > > > > On Tue, Nov 22, 2022 at 07:09:16PM -0700, Simon Glass wrote:
> > > > > > > > > > >  should be called 'priov' and should beHi Abdellatif,
> > > > > > > > > > >
> > > > > > > > >
> > > > > > > > > [..]
> > > > > > > > >
> > > > > > > > > > > > +/**
> > > > > > > > > > > > + * ffa_device_get - create, bind and probe the arm_ffa device
> > > > > > > > > > > > + * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created
> > > > > > > > > > > > + *       successfully)
> > > > > > > > > > > > + *
> > > > > > > > > > > > + * This function makes sure the arm_ffa device is
> > > > > > > > > > > > + * created, bound to this driver, probed and ready to use.
> > > > > > > > > > > > + * Arm FF-A transport is implemented through a single U-Boot
> > > > > > > > > > > > + * device managing the FF-A bus (arm_ffa).
> > > > > > > > > > > > + *
> > > > > > > > > > > > + * Return:
> > > > > > > > > > > > + *
> > > > > > > > > > > > + * 0 on success. Otherwise, failure
> > > > > > > > > > > > + */
> > > > > > > > > > > > +int ffa_device_get(struct udevice **pdev)
> > > > > > > > > > > > +{
> > > > > > > > > > > > +       int ret;
> > > > > > > > > > > > +       struct udevice *dev = NULL;
> > > > > > > > > > > > +
> > > > > > > > > > > > +       ret = device_bind(dm_root(), DM_DRIVER_GET(arm_ffa), FFA_DRV_NAME, NULL, ofnode_null(),
> > > > > > > > > > > > +                         &dev);
> > > > > > > > > > >
> > > > > > > > > > > Please add a DT binding. Even if only temporary, we need something for this.
> > > > > > > > > >
> > > > > > > > > > Thanks for the feedback. I'm happy to address all the comments.
> > > > > > > > > >
> > > > > > > > > > Regarding DT binding and FF-A discovery. We agreed with Linaro and Rob Herring
> > > > > > > > > > about the following:
> > > > > > > > > >
> > > > > > > > > > - DT is only for what we failed to make discoverable. For hardware, we're stuck
> > > > > > > > > >   with it. We shouldn't repeat that for software interfaces. This approach is
> > > > > > > > > >   already applied in the FF-A kernel driver which comes with no DT support and
> > > > > > > > > >   discovers the bus with bus_register() API [1].
> > > > > > > > >
> > > > > > > > > This may be the UEFI view, but it is not how U-Boot works. This is not something we are 'stuck' with. It is how we define what is present on a device. This is how the PCI bus works in U-Boot. It is best practice in U-Boot to use the device tree to make this things visible and configurable. Unlike with Linux there is no other way to provide configuration needed by these devices.
> > > > > > > >
> > > > > > > > Where do you get UEFI out of this?
> > > > > > >
> > > > > > > I assume it was UEFI as there was no discussion about this in U-Boot.
> > > > > > > Which firmware project was consulted about this?
> > > > > > >
> > > > > > > >
> > > > > > > > It is the discoverability of hardware that is fixed (and we are stuck
> > > > > > > > with). We can't change hardware. The disoverability may be PCI
> > > > > > > > VID/PID, USB device descriptors, or nothing. We only use DT when those
> > > > > > > > are not sufficient. For a software interface, there is no reason to
> > > > > > > > make them non-discoverable as the interface can be fixed (at least for
> > > > > > > > new things like FF-A).
> > > > > > >
> > > > > > > Here I am talking about the controller itself, the top-level node in
> > > > > > > the device tree. For PCI this is a device tree node and it should be
> > > > > > > the same here. So I am not saying that the devices on the bus need to
> > > > > > > be in the device tree (that can be optional, but may be useful in some
> > > > > > > situations where it is status and known).
> > > > > >
> > > > > > Sure, the PCI host bridges are not discoverable, have a bunch of
> > > > > > resources, and do need to be in DT. The downstream devices only do if
> > > > > > they have extra resources such as when a device is soldered down on a
> > > > > > board rather than a standard slot.
> > > > > >
> > > > > > > We need something like:
> > > > > > >
> > > > > > > ff-a {
> > > > > > >     compatible = "something";
> > > > > > > };
> > > > > > >
> > > > > > > I don't know what mechanism is actually used to communicate with it,
> > > > > > > but that will be enough to get the top-level driver started.
> > > > > >
> > > > > > There's discovery of FF-A itself and then discovery of FF-A features
> > > > > > (e.g. partitions). Both of those are discoverable without DT. The
> > > > > > first is done by checking the SMCCC version, then checking for FF-A
> > > > > > presence and features. Putting this into DT is redundant. Worse, what
> > > > > > if they disagree?
> > > > >
> > > > > Hi Simon,
> > > > >
> > > > > Do you agree with Rob, Ilias and myself that it makes more sense
> > > > > FF-A bus is discovered without a DT node and following the same approach as
> > > > > Linux ? (FF-A bus doesn't have a HW controller and is a purely SW bus,
> > > > > no configuration/description needed at DT level).
> > > > >
> > > > > Your suggestions are always welcome.
> > > >
> > > > I'm sorry I don't agree with that. It does need a compatible string,
> > > > like PCI has. You can just add it in U-Boot if Linux won't accept the
> > > > binding.
> > >
> > > It's not like PCI as the host side of PCI has non-discoverable resources.
> >
> > OK I see. It is certainly an edge case.
> >
> > >
> > > This all could have been designed better, but hindsight is 20/20 and
> > > things evolved step by step. There are a bunch of firmware services
> > > that are all behind SMCCC. The first (upstream) was PSCI. IIRC, SMCCC
> > > was invented a bit after that, but generalized PSCI for other
> > > services. Since then more have been added. More services get added one
> > > by one and yes we added bindings for them. Because what's one more...
> > > But that really needs to stop. We're stuck with h/w that's not
> > > discoverable, there's zero reason to do that with s/w interfaces. If
> > > we could redo everything, we'd have a node for SMCCC and that's it
> > > unless there's h/w resources provided to the rest of DT. But we can't,
> > > so SMCCC is discovered by the presence of PSCI.
> >
> > I understand the background here, but if we don't take a stand on
> > this, this sort of thing will continue.
> 
> I agree completely (but I think what you mean for 'this' is
> different). Using DT for s/w features has to stop.
> 
> Every new SMCCC firmware interface we get a new binding for it. FF-A
> originally had a bunch of crap in the binding. So did Op-tee. Why does
> each new firmware feature need a DT node? As software people, can't we
> design software interfaces which are discoverable on their own rather
> than using a hardware description for discovering them? The only part
> we can't discover is whether we have SMCCC or not, but we already have
> that in DT with the PSCI node because if we have PSCI, we have SMCCC.
> 
> It is the same problem with that UEFI SPI protocol binding on the list
> last week.

I guess the problem comes down to, can we have one discovery method that
everyone shares, or do we have to let everyone invent a new discovery
method every time? FF-A, Op-tee, U-Boot, coreboot, barebox (and
everyone else I'm unintentionally forgetting) could just discover these
things via device tree. Or, we could all write our own code to perform
the discovery.  And when RISC-V comes along with similar functionality,
we could probe their device tree and see they've implemented the same
concept, but a little differently, but still have the discovery portion
be in the device tree. To which it sounds like your answer is "not in
the device tree".

> > Just because something works
> > in Linux does not mean that the binding (or lack of it) is good.
> >
> > The reasons to do this are:
> > - avoids needing to manually call device_bind()
> > - avoids extra plumbing in U-Boot
> > - provides visibility into what is in the system, by looking at the
> > DT, like documentation
> > - DT is how devices are bound in U-Boot
> >
> > You can see the problem if you look at ffa_device_get(). It is called
> > from ffa_bus_discover() which is a new addition into the board_init
> > list. We are trying to remove this list and certainly don't want new
> > things added!!
> 
> That seems less than ideal. How do you init PSCI? Or u-boot doesn't
> touch it? The low-level code for both should be shared if not already.
> 
> > We don't need to change this in the Linux implementation, just add a
> > top-level DT node for U-Boot. I don't understand why that is such a
> > big problem?
> 
> It's a line in the sand. Yeah, 1 compatible is not a big deal, but
> then it is an invitation to add to the binding and add a compatible
> for the next SMCCC firmware feature.

Well, I suppose then that this is not the line in the sand we have to
have a larger debate about. For this, we'll just follow along with
what everyone else has agreed on re bindings, and that just leaves
Simon's other feedback about sandbox testing, etc.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-18 12:49                                                                 ` Tom Rini
@ 2023-01-18 13:46                                                                   ` Sudeep Holla
  2023-01-18 13:59                                                                     ` Tom Rini
  0 siblings, 1 reply; 478+ messages in thread
From: Sudeep Holla @ 2023-01-18 13:46 UTC (permalink / raw)
  To: Tom Rini, Sudeep Holla
  Cc: Rob Herring, Simon Glass, Abdellatif El Khlifi, ilias.apalodimas,
	jens.wiklander, achin.gupta, xueliang.zhong, u-boot

On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:

>
> I guess the problem comes down to, can we have one discovery method that
> everyone shares, or do we have to let everyone invent a new discovery
> method every time?


No one needs to invent any discovery method every time if the firmware
specification
provides one and as Rob mentioned many times in the thread, all new firmware
specification must provide one and we are trying to make sure that is
the case with all new
specs from Arm.


> FF-A, Op-tee, U-Boot, coreboot, barebox (and
> everyone else I'm unintentionally forgetting) could just discover these
> things via device tree.


I leave that to the individual projects to decide and agree but
fundamentally if
the specification provides a way to discover, not sure why we are even
discussing
an alternative method here.


> Or, we could all write our own code to perform
> the discovery.


For what reason ? I can understand if there is no discovery mechanism but
that's not the
case in $subject.


> And when RISC-V comes along with similar functionality,
> we could probe their device tree and see they've implemented the same
> concept, but a little differently, but still have the discovery portion
> be in the device tree. To which it sounds like your answer is "not in
> the device tree".
>

I see U-boot seem to have made a decision to create DT node for each and
everything
that needs to be added to DM which seems bit unfortunate but I don't
understand the
history/motive/background for it but I respect the decision if it is
already made.

These firmware interfaces are standard on all Arm platforms and can be
discovered
based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
addition of DT nodes for all the f/w i/f on all the platforms that need the
support when
one can be just discovered.

Sorry for the sudden appearance on this thread, I was avoiding getting into
this but thought
I will at least express my opinion and also the way the firmware
specifications from Arm is
expected to be evolved from now on. With that I will leave it to you and
other U-boot
maintainers and the community in general to decide the right course in this
case.

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-18 13:46                                                                   ` Sudeep Holla
@ 2023-01-18 13:59                                                                     ` Tom Rini
  2023-01-18 15:49                                                                       ` Sudeep Holla
  2023-01-19 16:31                                                                       ` Abdellatif El Khlifi
  0 siblings, 2 replies; 478+ messages in thread
From: Tom Rini @ 2023-01-18 13:59 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Rob Herring, Simon Glass, Abdellatif El Khlifi, ilias.apalodimas,
	jens.wiklander, achin.gupta, xueliang.zhong, u-boot

[-- Attachment #1: Type: text/plain, Size: 2611 bytes --]

On Wed, Jan 18, 2023 at 01:46:54PM +0000, Sudeep Holla wrote:
> On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:
> 
> >
> > I guess the problem comes down to, can we have one discovery method that
> > everyone shares, or do we have to let everyone invent a new discovery
> > method every time?
> 
> 
> No one needs to invent any discovery method every time if the firmware
> specification
> provides one and as Rob mentioned many times in the thread, all new firmware
> specification must provide one and we are trying to make sure that is
> the case with all new
> specs from Arm.
> 
> 
> > FF-A, Op-tee, U-Boot, coreboot, barebox (and
> > everyone else I'm unintentionally forgetting) could just discover these
> > things via device tree.
> 
> 
> I leave that to the individual projects to decide and agree but
> fundamentally if
> the specification provides a way to discover, not sure why we are even
> discussing
> an alternative method here.
> 
> 
> > Or, we could all write our own code to perform
> > the discovery.
> 
> 
> For what reason ? I can understand if there is no discovery mechanism but
> that's not the
> case in $subject.
> 
> 
> > And when RISC-V comes along with similar functionality,
> > we could probe their device tree and see they've implemented the same
> > concept, but a little differently, but still have the discovery portion
> > be in the device tree. To which it sounds like your answer is "not in
> > the device tree".
> >
> 
> I see U-boot seem to have made a decision to create DT node for each and
> everything
> that needs to be added to DM which seems bit unfortunate but I don't
> understand the
> history/motive/background for it but I respect the decision if it is
> already made.
> 
> These firmware interfaces are standard on all Arm platforms and can be
> discovered
> based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
> addition of DT nodes for all the f/w i/f on all the platforms that need the
> support when
> one can be just discovered.
> 
> Sorry for the sudden appearance on this thread, I was avoiding getting into
> this but thought
> I will at least express my opinion and also the way the firmware
> specifications from Arm is
> expected to be evolved from now on. With that I will leave it to you and
> other U-boot
> maintainers and the community in general to decide the right course in this
> case.

To be clear, if the position is that "this is what everyone else will
use, really" then yes, we'll follow this in U-Boot.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-18 13:59                                                                     ` Tom Rini
@ 2023-01-18 15:49                                                                       ` Sudeep Holla
  2023-01-19 16:31                                                                       ` Abdellatif El Khlifi
  1 sibling, 0 replies; 478+ messages in thread
From: Sudeep Holla @ 2023-01-18 15:49 UTC (permalink / raw)
  To: Tom Rini
  Cc: Rob Herring, Simon Glass, Abdellatif El Khlifi, ilias.apalodimas,
	jens.wiklander, Sudeep Holla, achin.gupta, xueliang.zhong,
	u-boot

On Wed, Jan 18, 2023 at 08:59:32AM -0500, Tom Rini wrote:
> To be clear, if the position is that "this is what everyone else will
> use, really" then yes, we'll follow this in U-Boot.

Well, that's difficult question to provide an assertive answer TBH.
I don't know all the projects using FF-A for example. I wasn't even aware
of U-Boot plans for it even being part of the same company. So lots of
things happen outside the company, in different community like this and
mainly without even Arm or interested party's involvement. I guess you
understand what I am trying to say here.

I or even Arm as a company can only provide suggestions when requested or
when interested developers like me happen to stumble across discussions
like this. I can never give you assurance that "everyone else will follow
our suggestion" unfortunately :(.

-- 
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-18 13:59                                                                     ` Tom Rini
  2023-01-18 15:49                                                                       ` Sudeep Holla
@ 2023-01-19 16:31                                                                       ` Abdellatif El Khlifi
  2023-01-19 16:40                                                                         ` Tom Rini
                                                                                           ` (2 more replies)
  1 sibling, 3 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-01-19 16:31 UTC (permalink / raw)
  To: sjg, trini
  Cc: achin.gupta, xueliang.zhong, Drew.Reed, sudeep.holla, robh,
	jens.wiklander, ilias.apalodimas, nd, u-boot

On Wed, Jan 18, 2023 at 08:59:32AM -0500, Tom Rini wrote:
> On Wed, Jan 18, 2023 at 01:46:54PM +0000, Sudeep Holla wrote:
> > On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:
> > 
> > >
> > > I guess the problem comes down to, can we have one discovery method that
> > > everyone shares, or do we have to let everyone invent a new discovery
> > > method every time?
> > 
> > 
> > No one needs to invent any discovery method every time if the firmware
> > specification
> > provides one and as Rob mentioned many times in the thread, all new firmware
> > specification must provide one and we are trying to make sure that is
> > the case with all new
> > specs from Arm.
> > 
> > 
> > > FF-A, Op-tee, U-Boot, coreboot, barebox (and
> > > everyone else I'm unintentionally forgetting) could just discover these
> > > things via device tree.
> > 
> > 
> > I leave that to the individual projects to decide and agree but
> > fundamentally if
> > the specification provides a way to discover, not sure why we are even
> > discussing
> > an alternative method here.
> > 
> > 
> > > Or, we could all write our own code to perform
> > > the discovery.
> > 
> > 
> > For what reason ? I can understand if there is no discovery mechanism but
> > that's not the
> > case in $subject.
> > 
> > 
> > > And when RISC-V comes along with similar functionality,
> > > we could probe their device tree and see they've implemented the same
> > > concept, but a little differently, but still have the discovery portion
> > > be in the device tree. To which it sounds like your answer is "not in
> > > the device tree".
> > >
> > 
> > I see U-boot seem to have made a decision to create DT node for each and
> > everything
> > that needs to be added to DM which seems bit unfortunate but I don't
> > understand the
> > history/motive/background for it but I respect the decision if it is
> > already made.
> > 
> > These firmware interfaces are standard on all Arm platforms and can be
> > discovered
> > based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
> > addition of DT nodes for all the f/w i/f on all the platforms that need the
> > support when
> > one can be just discovered.
> > 
> > Sorry for the sudden appearance on this thread, I was avoiding getting into
> > this but thought
> > I will at least express my opinion and also the way the firmware
> > specifications from Arm is
> > expected to be evolved from now on. With that I will leave it to you and
> > other U-boot
> > maintainers and the community in general to decide the right course in this
> > case.
> 
> To be clear, if the position is that "this is what everyone else will
> use, really" then yes, we'll follow this in U-Boot.

Hi Simon, Tom,

The FF-A transport is a SW bus and is not associated to any HW peripheral or
undiscoverable base address.

There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
interfaces. The FF-A spec [1] describes this in details.

Discovering means gathering information about the FF-A framework such as:
the FF-A version, supported features, secure partitions number and attributes.

Please refer to the following paragraphs for more details: [2], [3], [4], [5]

The core driver provided by this patchset implements the Setup and discovery interfaces
in addition to direct messaging.

The driver provides ffa_bus_discover() API that allows to discover the FF-A bus
as described by the spec and in the FF-A driver readme [6].

We expect and highly recommend FF-A users to always discover the FF-A bus using ffa_bus_discover() API.

A use case is provided which is the EFI MM communication [7].

ffa_bus_discover() does the following:

- creates, binds and probes the arm_ffa device
- at probe level, discovery FF-A interfaces are called to try to discover the FF-A framework
- when all discovery interfaces succeed, probing is successful and FF-A bus is ready to use
- if one of the discovery interfaces fails, the arm_ffa device is removed from the DM and
  FF-A bus can not be used


Cheers
Abdellatif

[1]: FF-A spec version 1.0, https://developer.arm.com/documentation/den0077/latest/

[2] 2.8 Partition identification and discovery

    All FF-A components can discover the identities and properties of other partitions through the FFA_PARTITION_INFO_GET
    interface. Once discovered, the IDs must be used in the messaging interfaces to identify the target of a message.

[3] 4.2.2.2 Buffer discovery and setup

    This version of the Framework enables discovery and setup of RX/TX buffer pairs between FF-A components as
    follows.

    ...

    2. An endpoint could allocate the buffer pair and use the FFA_RXTX_MAP interface to map it with the
    Hypervisor or SPM as applicable.

[4] 4.2.2.3 Buffer attributes

    An endpoint must discover the minimum size and alignment boundary for the RX/TX buffers by passing the
    function ID of the FFA_RXTX_MAP ABI as input in the FFA_FEATURES interface (see 8.2 FFA_FEATURES).

[5] 6.1.1 Common compliance requirements

    - It must be possible for the FF-A components at an FF-A instance to discover the presence and version number
    of their Framework implementations through the FFA_VERSION interface (see 8.1 FFA_VERSION).

    - All FF-A components must implement support for Setup and discovery interfaces described in Chapter 8
    Setup and discovery interfaces. These interfaces are as follows.

    FFA_VERSION.
    FFA_FEATURES.
    FFA_RX_RELEASE.
    FFA_RXTX_MAP.
    FFA_RXTX_UNMAP.
    FFA_PARTITION_INFO_GET.
    FFA_ID_GET.

    - It must be possible for an FF-A component, at the lower EL at an FF-A instance to use the FFA_FEATURES
    interface (see 8.2 FFA_FEATURES) to discover if an FF-A interface is implemented by the FF-A component
    at the higher EL.

[6] FF-A support readme: https://lore.kernel.org/all/20221122131751.22747-4-abdellatif.elkhlifi@arm.com/#Z31doc:arch:arm64.ffa.rst
[7] FF-A MM comms: https://lore.kernel.org/all/20221122131751.22747-10-abdellatif.elkhlifi@arm.com/
> 
> -- 
> Tom



^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 16:31                                                                       ` Abdellatif El Khlifi
@ 2023-01-19 16:40                                                                         ` Tom Rini
  2023-01-19 16:41                                                                         ` Simon Glass
  2023-01-19 16:46                                                                         ` [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver Sudeep Holla
  2 siblings, 0 replies; 478+ messages in thread
From: Tom Rini @ 2023-01-19 16:40 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: sjg, achin.gupta, xueliang.zhong, Drew.Reed, sudeep.holla, robh,
	jens.wiklander, ilias.apalodimas, nd, u-boot

[-- Attachment #1: Type: text/plain, Size: 7190 bytes --]

On Thu, Jan 19, 2023 at 04:31:57PM +0000, Abdellatif El Khlifi wrote:
> On Wed, Jan 18, 2023 at 08:59:32AM -0500, Tom Rini wrote:
> > On Wed, Jan 18, 2023 at 01:46:54PM +0000, Sudeep Holla wrote:
> > > On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:
> > > 
> > > >
> > > > I guess the problem comes down to, can we have one discovery method that
> > > > everyone shares, or do we have to let everyone invent a new discovery
> > > > method every time?
> > > 
> > > 
> > > No one needs to invent any discovery method every time if the firmware
> > > specification
> > > provides one and as Rob mentioned many times in the thread, all new firmware
> > > specification must provide one and we are trying to make sure that is
> > > the case with all new
> > > specs from Arm.
> > > 
> > > 
> > > > FF-A, Op-tee, U-Boot, coreboot, barebox (and
> > > > everyone else I'm unintentionally forgetting) could just discover these
> > > > things via device tree.
> > > 
> > > 
> > > I leave that to the individual projects to decide and agree but
> > > fundamentally if
> > > the specification provides a way to discover, not sure why we are even
> > > discussing
> > > an alternative method here.
> > > 
> > > 
> > > > Or, we could all write our own code to perform
> > > > the discovery.
> > > 
> > > 
> > > For what reason ? I can understand if there is no discovery mechanism but
> > > that's not the
> > > case in $subject.
> > > 
> > > 
> > > > And when RISC-V comes along with similar functionality,
> > > > we could probe their device tree and see they've implemented the same
> > > > concept, but a little differently, but still have the discovery portion
> > > > be in the device tree. To which it sounds like your answer is "not in
> > > > the device tree".
> > > >
> > > 
> > > I see U-boot seem to have made a decision to create DT node for each and
> > > everything
> > > that needs to be added to DM which seems bit unfortunate but I don't
> > > understand the
> > > history/motive/background for it but I respect the decision if it is
> > > already made.
> > > 
> > > These firmware interfaces are standard on all Arm platforms and can be
> > > discovered
> > > based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
> > > addition of DT nodes for all the f/w i/f on all the platforms that need the
> > > support when
> > > one can be just discovered.
> > > 
> > > Sorry for the sudden appearance on this thread, I was avoiding getting into
> > > this but thought
> > > I will at least express my opinion and also the way the firmware
> > > specifications from Arm is
> > > expected to be evolved from now on. With that I will leave it to you and
> > > other U-boot
> > > maintainers and the community in general to decide the right course in this
> > > case.
> > 
> > To be clear, if the position is that "this is what everyone else will
> > use, really" then yes, we'll follow this in U-Boot.
> 
> Hi Simon, Tom,
> 
> The FF-A transport is a SW bus and is not associated to any HW peripheral or
> undiscoverable base address.
> 
> There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> interfaces. The FF-A spec [1] describes this in details.
> 
> Discovering means gathering information about the FF-A framework such as:
> the FF-A version, supported features, secure partitions number and attributes.
> 
> Please refer to the following paragraphs for more details: [2], [3], [4], [5]
> 
> The core driver provided by this patchset implements the Setup and discovery interfaces
> in addition to direct messaging.
> 
> The driver provides ffa_bus_discover() API that allows to discover the FF-A bus
> as described by the spec and in the FF-A driver readme [6].
> 
> We expect and highly recommend FF-A users to always discover the FF-A bus using ffa_bus_discover() API.
> 
> A use case is provided which is the EFI MM communication [7].
> 
> ffa_bus_discover() does the following:
> 
> - creates, binds and probes the arm_ffa device
> - at probe level, discovery FF-A interfaces are called to try to discover the FF-A framework
> - when all discovery interfaces succeed, probing is successful and FF-A bus is ready to use
> - if one of the discovery interfaces fails, the arm_ffa device is removed from the DM and
>   FF-A bus can not be used
> 
> 
> Cheers
> Abdellatif
> 
> [1]: FF-A spec version 1.0, https://developer.arm.com/documentation/den0077/latest/
> 
> [2] 2.8 Partition identification and discovery
> 
>     All FF-A components can discover the identities and properties of other partitions through the FFA_PARTITION_INFO_GET
>     interface. Once discovered, the IDs must be used in the messaging interfaces to identify the target of a message.
> 
> [3] 4.2.2.2 Buffer discovery and setup
> 
>     This version of the Framework enables discovery and setup of RX/TX buffer pairs between FF-A components as
>     follows.
> 
>     ...
> 
>     2. An endpoint could allocate the buffer pair and use the FFA_RXTX_MAP interface to map it with the
>     Hypervisor or SPM as applicable.
> 
> [4] 4.2.2.3 Buffer attributes
> 
>     An endpoint must discover the minimum size and alignment boundary for the RX/TX buffers by passing the
>     function ID of the FFA_RXTX_MAP ABI as input in the FFA_FEATURES interface (see 8.2 FFA_FEATURES).
> 
> [5] 6.1.1 Common compliance requirements
> 
>     - It must be possible for the FF-A components at an FF-A instance to discover the presence and version number
>     of their Framework implementations through the FFA_VERSION interface (see 8.1 FFA_VERSION).
> 
>     - All FF-A components must implement support for Setup and discovery interfaces described in Chapter 8
>     Setup and discovery interfaces. These interfaces are as follows.
> 
>     FFA_VERSION.
>     FFA_FEATURES.
>     FFA_RX_RELEASE.
>     FFA_RXTX_MAP.
>     FFA_RXTX_UNMAP.
>     FFA_PARTITION_INFO_GET.
>     FFA_ID_GET.
> 
>     - It must be possible for an FF-A component, at the lower EL at an FF-A instance to use the FFA_FEATURES
>     interface (see 8.2 FFA_FEATURES) to discover if an FF-A interface is implemented by the FF-A component
>     at the higher EL.
> 
> [6] FF-A support readme: https://lore.kernel.org/all/20221122131751.22747-4-abdellatif.elkhlifi@arm.com/#Z31doc:arch:arm64.ffa.rst
> [7] FF-A MM comms: https://lore.kernel.org/all/20221122131751.22747-10-abdellatif.elkhlifi@arm.com/

Since I'm apparently being unclear, let me try again. Yes, fine, for
U-Boot, we'll go ahead and accept patches that implement this spec, and
not require device tree modifications.

But as also I believe been agreed on, this doesn't prevent some other
architecture / group from coming along and claiming it has a new unique
approach to this problem and so has to re-invent the discoverable
software bus wheel. Nor does it prevent some group from inventing a
different software defined bus and discovery method and not re-using any
of this work, because it too is special and unique and somehow different
enough.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 16:31                                                                       ` Abdellatif El Khlifi
  2023-01-19 16:40                                                                         ` Tom Rini
@ 2023-01-19 16:41                                                                         ` Simon Glass
  2023-01-19 16:43                                                                           ` Tom Rini
                                                                                             ` (2 more replies)
  2023-01-19 16:46                                                                         ` [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver Sudeep Holla
  2 siblings, 3 replies; 478+ messages in thread
From: Simon Glass @ 2023-01-19 16:41 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: trini, achin.gupta, xueliang.zhong, Drew.Reed, sudeep.holla,
	robh, jens.wiklander, ilias.apalodimas, nd, u-boot

Hi Abdellatif,

On Thu, 19 Jan 2023 at 09:32, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> On Wed, Jan 18, 2023 at 08:59:32AM -0500, Tom Rini wrote:
> > On Wed, Jan 18, 2023 at 01:46:54PM +0000, Sudeep Holla wrote:
> > > On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:
> > >
> > > >
> > > > I guess the problem comes down to, can we have one discovery method that
> > > > everyone shares, or do we have to let everyone invent a new discovery
> > > > method every time?
> > >
> > >
> > > No one needs to invent any discovery method every time if the firmware
> > > specification
> > > provides one and as Rob mentioned many times in the thread, all new firmware
> > > specification must provide one and we are trying to make sure that is
> > > the case with all new
> > > specs from Arm.
> > >
> > >
> > > > FF-A, Op-tee, U-Boot, coreboot, barebox (and
> > > > everyone else I'm unintentionally forgetting) could just discover these
> > > > things via device tree.
> > >
> > >
> > > I leave that to the individual projects to decide and agree but
> > > fundamentally if
> > > the specification provides a way to discover, not sure why we are even
> > > discussing
> > > an alternative method here.
> > >
> > >
> > > > Or, we could all write our own code to perform
> > > > the discovery.
> > >
> > >
> > > For what reason ? I can understand if there is no discovery mechanism but
> > > that's not the
> > > case in $subject.
> > >
> > >
> > > > And when RISC-V comes along with similar functionality,
> > > > we could probe their device tree and see they've implemented the same
> > > > concept, but a little differently, but still have the discovery portion
> > > > be in the device tree. To which it sounds like your answer is "not in
> > > > the device tree".
> > > >
> > >
> > > I see U-boot seem to have made a decision to create DT node for each and
> > > everything
> > > that needs to be added to DM which seems bit unfortunate but I don't
> > > understand the
> > > history/motive/background for it but I respect the decision if it is
> > > already made.
> > >
> > > These firmware interfaces are standard on all Arm platforms and can be
> > > discovered
> > > based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
> > > addition of DT nodes for all the f/w i/f on all the platforms that need the
> > > support when
> > > one can be just discovered.
> > >
> > > Sorry for the sudden appearance on this thread, I was avoiding getting into
> > > this but thought
> > > I will at least express my opinion and also the way the firmware
> > > specifications from Arm is
> > > expected to be evolved from now on. With that I will leave it to you and
> > > other U-boot
> > > maintainers and the community in general to decide the right course in this
> > > case.
> >
> > To be clear, if the position is that "this is what everyone else will
> > use, really" then yes, we'll follow this in U-Boot.
>
> Hi Simon, Tom,
>
> The FF-A transport is a SW bus and is not associated to any HW peripheral or
> undiscoverable base address.
>
> There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> interfaces. The FF-A spec [1] describes this in details.

Can you add a DT node for the 'FF-A SW interfaces' and attach some
sort of top-level driver to that? Perhaps simple-bus, or your own
thing? You don't need to add compatible strings for subnodes (devices
that are discoverable within that).

If you don't want to submit the compatible string to Linux, I will do
it. If it has to have a 'u-boot,' prefix then so be it, but I don't
see why that is necessary, since Linux can ignore it if it likes.

We have been talking about this for far too long, IMO. Would you like
me to send a patch? It is something like this:

ff-a {
    compatible = "arm,ff-a";
};

>
> Discovering means gathering information about the FF-A framework such as:
> the FF-A version, supported features, secure partitions number and attributes.
>
> Please refer to the following paragraphs for more details: [2], [3], [4], [5]
>
> The core driver provided by this patchset implements the Setup and discovery interfaces
> in addition to direct messaging.
>
> The driver provides ffa_bus_discover() API that allows to discover the FF-A bus
> as described by the spec and in the FF-A driver readme [6].
>
> We expect and highly recommend FF-A users to always discover the FF-A bus using ffa_bus_discover() API.
>
> A use case is provided which is the EFI MM communication [7].
>
> ffa_bus_discover() does the following:
>
> - creates, binds and probes the arm_ffa device
> - at probe level, discovery FF-A interfaces are called to try to discover the FF-A framework
> - when all discovery interfaces succeed, probing is successful and FF-A bus is ready to use
> - if one of the discovery interfaces fails, the arm_ffa device is removed from the DM and
>   FF-A bus can not be used

This is not how things are supposed to work in U-Boot. Please read the
documentation which is here:

https://u-boot.readthedocs.io/en/latest/develop/driver-model/index.html

So referencing above:

1, No, the binding of the ff-a device should happen automatically from the DT
2. probing ff-a causes the other devices to be bound (as with PCI,
USB, every other bus in U-Boot)
3. Yes
4. No, you must not unbind it. It just sits there unprobed and cannot
be used. We might want to have a command that looks at what is wrong
with it. Probing the device should produce an error, as with every
other device in U-Boot

I am happy to discuss this on a call if we really cannot do this by
email. Or I can send a patch...but please read the documentation and
avoid adding special cases for this interface.

Regards,
Simon


>
>
> Cheers
> Abdellatif
>
> [1]: FF-A spec version 1.0, https://developer.arm.com/documentation/den0077/latest/
>
> [2] 2.8 Partition identification and discovery
>
>     All FF-A components can discover the identities and properties of other partitions through the FFA_PARTITION_INFO_GET
>     interface. Once discovered, the IDs must be used in the messaging interfaces to identify the target of a message.
>
> [3] 4.2.2.2 Buffer discovery and setup
>
>     This version of the Framework enables discovery and setup of RX/TX buffer pairs between FF-A components as
>     follows.
>
>     ...
>
>     2. An endpoint could allocate the buffer pair and use the FFA_RXTX_MAP interface to map it with the
>     Hypervisor or SPM as applicable.
>
> [4] 4.2.2.3 Buffer attributes
>
>     An endpoint must discover the minimum size and alignment boundary for the RX/TX buffers by passing the
>     function ID of the FFA_RXTX_MAP ABI as input in the FFA_FEATURES interface (see 8.2 FFA_FEATURES).
>
> [5] 6.1.1 Common compliance requirements
>
>     - It must be possible for the FF-A components at an FF-A instance to discover the presence and version number
>     of their Framework implementations through the FFA_VERSION interface (see 8.1 FFA_VERSION).
>
>     - All FF-A components must implement support for Setup and discovery interfaces described in Chapter 8
>     Setup and discovery interfaces. These interfaces are as follows.
>
>     FFA_VERSION.
>     FFA_FEATURES.
>     FFA_RX_RELEASE.
>     FFA_RXTX_MAP.
>     FFA_RXTX_UNMAP.
>     FFA_PARTITION_INFO_GET.
>     FFA_ID_GET.
>
>     - It must be possible for an FF-A component, at the lower EL at an FF-A instance to use the FFA_FEATURES
>     interface (see 8.2 FFA_FEATURES) to discover if an FF-A interface is implemented by the FF-A component
>     at the higher EL.
>
> [6] FF-A support readme: https://lore.kernel.org/all/20221122131751.22747-4-abdellatif.elkhlifi@arm.com/#Z31doc:arch:arm64.ffa.rst
> [7] FF-A MM comms: https://lore.kernel.org/all/20221122131751.22747-10-abdellatif.elkhlifi@arm.com/
> >
> > --
> > Tom
>
>

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 16:41                                                                         ` Simon Glass
@ 2023-01-19 16:43                                                                           ` Tom Rini
  2023-01-19 16:56                                                                           ` Sudeep Holla
  2023-01-19 18:11                                                                           ` Rob Herring
  2 siblings, 0 replies; 478+ messages in thread
From: Tom Rini @ 2023-01-19 16:43 UTC (permalink / raw)
  To: Simon Glass
  Cc: Abdellatif El Khlifi, achin.gupta, xueliang.zhong, Drew.Reed,
	sudeep.holla, robh, jens.wiklander, ilias.apalodimas, nd, u-boot

[-- Attachment #1: Type: text/plain, Size: 4468 bytes --]

On Thu, Jan 19, 2023 at 09:41:12AM -0700, Simon Glass wrote:
> Hi Abdellatif,
> 
> On Thu, 19 Jan 2023 at 09:32, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > On Wed, Jan 18, 2023 at 08:59:32AM -0500, Tom Rini wrote:
> > > On Wed, Jan 18, 2023 at 01:46:54PM +0000, Sudeep Holla wrote:
> > > > On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > >
> > > > > I guess the problem comes down to, can we have one discovery method that
> > > > > everyone shares, or do we have to let everyone invent a new discovery
> > > > > method every time?
> > > >
> > > >
> > > > No one needs to invent any discovery method every time if the firmware
> > > > specification
> > > > provides one and as Rob mentioned many times in the thread, all new firmware
> > > > specification must provide one and we are trying to make sure that is
> > > > the case with all new
> > > > specs from Arm.
> > > >
> > > >
> > > > > FF-A, Op-tee, U-Boot, coreboot, barebox (and
> > > > > everyone else I'm unintentionally forgetting) could just discover these
> > > > > things via device tree.
> > > >
> > > >
> > > > I leave that to the individual projects to decide and agree but
> > > > fundamentally if
> > > > the specification provides a way to discover, not sure why we are even
> > > > discussing
> > > > an alternative method here.
> > > >
> > > >
> > > > > Or, we could all write our own code to perform
> > > > > the discovery.
> > > >
> > > >
> > > > For what reason ? I can understand if there is no discovery mechanism but
> > > > that's not the
> > > > case in $subject.
> > > >
> > > >
> > > > > And when RISC-V comes along with similar functionality,
> > > > > we could probe their device tree and see they've implemented the same
> > > > > concept, but a little differently, but still have the discovery portion
> > > > > be in the device tree. To which it sounds like your answer is "not in
> > > > > the device tree".
> > > > >
> > > >
> > > > I see U-boot seem to have made a decision to create DT node for each and
> > > > everything
> > > > that needs to be added to DM which seems bit unfortunate but I don't
> > > > understand the
> > > > history/motive/background for it but I respect the decision if it is
> > > > already made.
> > > >
> > > > These firmware interfaces are standard on all Arm platforms and can be
> > > > discovered
> > > > based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
> > > > addition of DT nodes for all the f/w i/f on all the platforms that need the
> > > > support when
> > > > one can be just discovered.
> > > >
> > > > Sorry for the sudden appearance on this thread, I was avoiding getting into
> > > > this but thought
> > > > I will at least express my opinion and also the way the firmware
> > > > specifications from Arm is
> > > > expected to be evolved from now on. With that I will leave it to you and
> > > > other U-boot
> > > > maintainers and the community in general to decide the right course in this
> > > > case.
> > >
> > > To be clear, if the position is that "this is what everyone else will
> > > use, really" then yes, we'll follow this in U-Boot.
> >
> > Hi Simon, Tom,
> >
> > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > undiscoverable base address.
> >
> > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > interfaces. The FF-A spec [1] describes this in details.
> 
> Can you add a DT node for the 'FF-A SW interfaces' and attach some
> sort of top-level driver to that? Perhaps simple-bus, or your own
> thing? You don't need to add compatible strings for subnodes (devices
> that are discoverable within that).
> 
> If you don't want to submit the compatible string to Linux, I will do
> it. If it has to have a 'u-boot,' prefix then so be it, but I don't
> see why that is necessary, since Linux can ignore it if it likes.
> 
> We have been talking about this for far too long, IMO. Would you like
> me to send a patch? It is something like this:
> 
> ff-a {
>     compatible = "arm,ff-a";
> };

No, we don't need a DT node here. Everyone else is insisting that we can
solve the problems without it. So, lets go ahead and prove it. The
approach they're describing can be integrated without a device tree
node, in to the rest of the framework we  have.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 16:31                                                                       ` Abdellatif El Khlifi
  2023-01-19 16:40                                                                         ` Tom Rini
  2023-01-19 16:41                                                                         ` Simon Glass
@ 2023-01-19 16:46                                                                         ` Sudeep Holla
  2023-01-19 16:54                                                                           ` Simon Glass
  2 siblings, 1 reply; 478+ messages in thread
From: Sudeep Holla @ 2023-01-19 16:46 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: sjg, trini, achin.gupta, xueliang.zhong, Drew.Reed, robh,
	jens.wiklander, ilias.apalodimas, Sudeep Holla, u-boot

Hi Abdellatif,

On Thu, Jan 19, 2023 at 04:31:57PM +0000, Abdellatif El Khlifi wrote:
>
> Hi Simon, Tom,
>
> The FF-A transport is a SW bus and is not associated to any HW peripheral or
> undiscoverable base address.
>
> There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> interfaces. The FF-A spec [1] describes this in details.
>
> Discovering means gathering information about the FF-A framework such as:
> the FF-A version, supported features, secure partitions number and attributes.
>
> Please refer to the following paragraphs for more details: [2], [3], [4], [5]
>
> The core driver provided by this patchset implements the Setup and discovery interfaces
> in addition to direct messaging.
>
> The driver provides ffa_bus_discover() API that allows to discover the FF-A bus
> as described by the spec and in the FF-A driver readme [6].
>
> We expect and highly recommend FF-A users to always discover the FF-A bus using ffa_bus_discover() API.
>

Thanks for the details. But IIRC this discussion is not about the FF-A bus
and device(partitions) discovery, but the support for FF-A itself. The
discussion is about where to have a device node to represent the existence of
FF-A support on a platform. If we are talking about individual partitions
(devices) in the device tree, then that is pure stupidity as it goes out
of since with the firmware the moment a partition is added or removed in
the firmware.

IIUC, the whole discussion was around whether to use FFA_VERSION as the
discovery mechanism for existence of FF-A support on a platform or you
have a device node to specify the same.

Just to be clear, even if it is decided to add a device node, the
FFA_VERSION must be used to detect the presence of FF-A support and
return error otherwise. DT node presence is just to satisfy the design
and must be treated as no auto-confirmation for the presence of FF-A
support. We are just arguing the device node presence is just redundant,
but as mentioned before it is up to U-Boot community to make a call on
what is best.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 16:46                                                                         ` [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver Sudeep Holla
@ 2023-01-19 16:54                                                                           ` Simon Glass
  2023-01-19 16:57                                                                             ` Tom Rini
  2023-01-19 17:00                                                                             ` Sudeep Holla
  0 siblings, 2 replies; 478+ messages in thread
From: Simon Glass @ 2023-01-19 16:54 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Abdellatif El Khlifi, trini, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, ilias.apalodimas, u-boot

Hi Sudeep,

On Thu, 19 Jan 2023 at 09:46, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> Hi Abdellatif,
>
> On Thu, Jan 19, 2023 at 04:31:57PM +0000, Abdellatif El Khlifi wrote:
> >
> > Hi Simon, Tom,
> >
> > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > undiscoverable base address.
> >
> > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > interfaces. The FF-A spec [1] describes this in details.
> >
> > Discovering means gathering information about the FF-A framework such as:
> > the FF-A version, supported features, secure partitions number and attributes.
> >
> > Please refer to the following paragraphs for more details: [2], [3], [4], [5]
> >
> > The core driver provided by this patchset implements the Setup and discovery interfaces
> > in addition to direct messaging.
> >
> > The driver provides ffa_bus_discover() API that allows to discover the FF-A bus
> > as described by the spec and in the FF-A driver readme [6].
> >
> > We expect and highly recommend FF-A users to always discover the FF-A bus using ffa_bus_discover() API.
> >
>
> Thanks for the details. But IIRC this discussion is not about the FF-A bus
> and device(partitions) discovery, but the support for FF-A itself. The
> discussion is about where to have a device node to represent the existence of
> FF-A support on a platform. If we are talking about individual partitions
> (devices) in the device tree, then that is pure stupidity as it goes out
> of since with the firmware the moment a partition is added or removed in
> the firmware.
>
> IIUC, the whole discussion was around whether to use FFA_VERSION as the
> discovery mechanism for existence of FF-A support on a platform or you
> have a device node to specify the same.

No, with respect, that is not quite the situation here.

>
> Just to be clear, even if it is decided to add a device node, the
> FFA_VERSION must be used to detect the presence of FF-A support and
> return error otherwise. DT node presence is just to satisfy the design
> and must be treated as no auto-confirmation for the presence of FF-A
> support. We are just arguing the device node presence is just redundant,
> but as mentioned before it is up to U-Boot community to make a call on
> what is best.

U-Boot driver model design already supports this. You can have a
device that binds (from DT) but will not probe because it is not
present / wrong version. Perhaps this was missed in the conversion to
Linux:

https://u-boot.readthedocs.io/en/latest/develop/driver-model/design.html#driver-lifecycle

So there is nothing clever needed here at all and anything you do just
adds confusion and bad precedent.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 16:41                                                                         ` Simon Glass
  2023-01-19 16:43                                                                           ` Tom Rini
@ 2023-01-19 16:56                                                                           ` Sudeep Holla
  2023-01-20  9:56                                                                             ` Abdellatif El Khlifi
  2023-01-19 18:11                                                                           ` Rob Herring
  2 siblings, 1 reply; 478+ messages in thread
From: Sudeep Holla @ 2023-01-19 16:56 UTC (permalink / raw)
  To: Simon Glass
  Cc: Abdellatif El Khlifi, trini, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, ilias.apalodimas, nd, u-boot,
	Sudeep Holla

Hi Simon,

(sorry we just crossed the emails)

On Thu, Jan 19, 2023 at 09:41:12AM -0700, Simon Glass wrote:
>
> Can you add a DT node for the 'FF-A SW interfaces' and attach some
> sort of top-level driver to that? Perhaps simple-bus, or your own
> thing? You don't need to add compatible strings for subnodes (devices
> that are discoverable within that).
>

Thanks for putting this nicely. I just wrote the same thing probably in
not so simpler way. But I agree with you as Abdellatif last email talks
more around sub-nodes or child device nodes (devices that are discoverable
within that)

> If you don't want to submit the compatible string to Linux, I will do
> it. If it has to have a 'u-boot,' prefix then so be it, but I don't
> see why that is necessary, since Linux can ignore it if it likes.
>
> We have been talking about this for far too long, IMO. Would you like
> me to send a patch? It is something like this:
>
> ff-a {
>     compatible = "arm,ff-a";
> };
>

Makes sense if DT node is the only way. It should be as simple as this
and presence of this must not imply presence of FF-A feature on the
platform. The driver must check using FFA_VERSION

> >
> > Discovering means gathering information about the FF-A framework such as:
> > the FF-A version, supported features, secure partitions number and attributes.
> >
> > Please refer to the following paragraphs for more details: [2], [3], [4], [5]
> >
> > The core driver provided by this patchset implements the Setup and discovery interfaces
> > in addition to direct messaging.
> >
> > The driver provides ffa_bus_discover() API that allows to discover the FF-A bus
> > as described by the spec and in the FF-A driver readme [6].
> >
> > We expect and highly recommend FF-A users to always discover the FF-A bus using ffa_bus_discover() API.
> >
> > A use case is provided which is the EFI MM communication [7].
> >
> > ffa_bus_discover() does the following:
> >
> > - creates, binds and probes the arm_ffa device
> > - at probe level, discovery FF-A interfaces are called to try to discover the FF-A framework
> > - when all discovery interfaces succeed, probing is successful and FF-A bus is ready to use
> > - if one of the discovery interfaces fails, the arm_ffa device is removed from the DM and
> >   FF-A bus can not be used
>
> This is not how things are supposed to work in U-Boot. Please read the
> documentation which is here:
>
> https://u-boot.readthedocs.io/en/latest/develop/driver-model/index.html
>
> So referencing above:
>
> 1, No, the binding of the ff-a device should happen automatically from the DT
> 2. probing ff-a causes the other devices to be bound (as with PCI,
> USB, every other bus in U-Boot)
> 3. Yes
> 4. No, you must not unbind it. It just sits there unprobed and cannot
> be used. We might want to have a command that looks at what is wrong
> with it. Probing the device should produce an error, as with every
> other device in U-Boot
>

Agreed on all points(assuming DT way here). Especially the last point,
there is no point is rolling back if one partion/device initialisation
fails or is not bound.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 16:54                                                                           ` Simon Glass
@ 2023-01-19 16:57                                                                             ` Tom Rini
  2023-01-19 17:09                                                                               ` Sudeep Holla
  2023-01-19 17:21                                                                               ` Simon Glass
  2023-01-19 17:00                                                                             ` Sudeep Holla
  1 sibling, 2 replies; 478+ messages in thread
From: Tom Rini @ 2023-01-19 16:57 UTC (permalink / raw)
  To: Simon Glass
  Cc: Sudeep Holla, Abdellatif El Khlifi, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, ilias.apalodimas, u-boot

[-- Attachment #1: Type: text/plain, Size: 3321 bytes --]

On Thu, Jan 19, 2023 at 09:54:29AM -0700, Simon Glass wrote:
> Hi Sudeep,
> 
> On Thu, 19 Jan 2023 at 09:46, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > Hi Abdellatif,
> >
> > On Thu, Jan 19, 2023 at 04:31:57PM +0000, Abdellatif El Khlifi wrote:
> > >
> > > Hi Simon, Tom,
> > >
> > > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > > undiscoverable base address.
> > >
> > > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > > interfaces. The FF-A spec [1] describes this in details.
> > >
> > > Discovering means gathering information about the FF-A framework such as:
> > > the FF-A version, supported features, secure partitions number and attributes.
> > >
> > > Please refer to the following paragraphs for more details: [2], [3], [4], [5]
> > >
> > > The core driver provided by this patchset implements the Setup and discovery interfaces
> > > in addition to direct messaging.
> > >
> > > The driver provides ffa_bus_discover() API that allows to discover the FF-A bus
> > > as described by the spec and in the FF-A driver readme [6].
> > >
> > > We expect and highly recommend FF-A users to always discover the FF-A bus using ffa_bus_discover() API.
> > >
> >
> > Thanks for the details. But IIRC this discussion is not about the FF-A bus
> > and device(partitions) discovery, but the support for FF-A itself. The
> > discussion is about where to have a device node to represent the existence of
> > FF-A support on a platform. If we are talking about individual partitions
> > (devices) in the device tree, then that is pure stupidity as it goes out
> > of since with the firmware the moment a partition is added or removed in
> > the firmware.
> >
> > IIUC, the whole discussion was around whether to use FFA_VERSION as the
> > discovery mechanism for existence of FF-A support on a platform or you
> > have a device node to specify the same.
> 
> No, with respect, that is not quite the situation here.
> 
> >
> > Just to be clear, even if it is decided to add a device node, the
> > FFA_VERSION must be used to detect the presence of FF-A support and
> > return error otherwise. DT node presence is just to satisfy the design
> > and must be treated as no auto-confirmation for the presence of FF-A
> > support. We are just arguing the device node presence is just redundant,
> > but as mentioned before it is up to U-Boot community to make a call on
> > what is best.
> 
> U-Boot driver model design already supports this. You can have a
> device that binds (from DT) but will not probe because it is not
> present / wrong version. Perhaps this was missed in the conversion to
> Linux:
> 
> https://u-boot.readthedocs.io/en/latest/develop/driver-model/design.html#driver-lifecycle
> 
> So there is nothing clever needed here at all and anything you do just
> adds confusion and bad precedent.

But it's also true that at run-time, within U-Boot, we can modify the
device tree we have, with live tree yes? So, the whole series in
question here can be done without modifying the base DT and getting in
to the further discussions that doing so entails. The assertion is that
the software discoverable bus here is sufficient to not need DT, so, OK,
lets go.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 16:54                                                                           ` Simon Glass
  2023-01-19 16:57                                                                             ` Tom Rini
@ 2023-01-19 17:00                                                                             ` Sudeep Holla
  1 sibling, 0 replies; 478+ messages in thread
From: Sudeep Holla @ 2023-01-19 17:00 UTC (permalink / raw)
  To: Simon Glass
  Cc: Abdellatif El Khlifi, trini, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, Sudeep Holla, ilias.apalodimas,
	u-boot

On Thu, Jan 19, 2023 at 09:54:29AM -0700, Simon Glass wrote:
> Hi Sudeep,
> 
> On Thu, 19 Jan 2023 at 09:46, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > Thanks for the details. But IIRC this discussion is not about the FF-A bus
> > and device(partitions) discovery, but the support for FF-A itself. The
> > discussion is about where to have a device node to represent the existence of
> > FF-A support on a platform. If we are talking about individual partitions
> > (devices) in the device tree, then that is pure stupidity as it goes out
> > of since with the firmware the moment a partition is added or removed in
> > the firmware.
> >
> > IIUC, the whole discussion was around whether to use FFA_VERSION as the
> > discovery mechanism for existence of FF-A support on a platform or you
> > have a device node to specify the same.
> 
> No, with respect, that is not quite the situation here.
>

Hmm, not sure what you mean by that. Based on your earlier response, I
thought we are in agreement but you sound to differ here. Am I missing
something ?

> >
> > Just to be clear, even if it is decided to add a device node, the
> > FFA_VERSION must be used to detect the presence of FF-A support and
> > return error otherwise. DT node presence is just to satisfy the design
> > and must be treated as no auto-confirmation for the presence of FF-A
> > support. We are just arguing the device node presence is just redundant,
> > but as mentioned before it is up to U-Boot community to make a call on
> > what is best.
> 
> U-Boot driver model design already supports this. You can have a
> device that binds (from DT) but will not probe because it is not
> present / wrong version. Perhaps this was missed in the conversion to
> Linux:
> 
> https://u-boot.readthedocs.io/en/latest/develop/driver-model/design.html#driver-lifecycle
> 
> So there is nothing clever needed here at all and anything you do just
> adds confusion and bad precedent.
>

OK, I will give that a read.

-- 
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 16:57                                                                             ` Tom Rini
@ 2023-01-19 17:09                                                                               ` Sudeep Holla
  2023-01-19 17:21                                                                                 ` Tom Rini
  2023-01-19 17:22                                                                                 ` Simon Glass
  2023-01-19 17:21                                                                               ` Simon Glass
  1 sibling, 2 replies; 478+ messages in thread
From: Sudeep Holla @ 2023-01-19 17:09 UTC (permalink / raw)
  To: Tom Rini
  Cc: Simon Glass, Abdellatif El Khlifi, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, ilias.apalodimas, u-boot,
	Sudeep Holla

On Thu, Jan 19, 2023 at 11:57:44AM -0500, Tom Rini wrote:
>
> But it's also true that at run-time, within U-Boot, we can modify the
> device tree we have, with live tree yes? So, the whole series in
> question here can be done without modifying the base DT and getting in
> to the further discussions that doing so entails. The assertion is that
> the software discoverable bus here is sufficient to not need DT, so, OK,
> lets go.

OK, may be I am not up-to-date on the U-Boot. IIUC, the modifications
done in the DT by U-Boot is mostly for consumption by the next stage
loader/OS and not for self-consumption. But if it is for self consumption,
then good. It helps especially for the subnodes(as Simon referred) or the
partitions that can be discovered at run-time using FF-A interface.

As mentioned I am not again DT, it is just not needed and especially
for subnodes it could result in inconsistency b/w what is in DT and
what the firmware provides. As mentioned in previous response, having a
simple node that Simon provided as example earlier is fine by me if that
is the only option to make progress as I just feel it is redundant and
one can say not scalable(but that is debatable again 😄).

In short, I am not concerned about having simple node, just don't like
to see entire FF-A bus enumerated in DT as subnodes for reasons mentioned
already.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 16:57                                                                             ` Tom Rini
  2023-01-19 17:09                                                                               ` Sudeep Holla
@ 2023-01-19 17:21                                                                               ` Simon Glass
  2023-01-19 17:24                                                                                 ` Tom Rini
  1 sibling, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-01-19 17:21 UTC (permalink / raw)
  To: Tom Rini
  Cc: Sudeep Holla, Abdellatif El Khlifi, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, ilias.apalodimas, u-boot

Hi Tom,

On Thu, 19 Jan 2023 at 09:57, Tom Rini <trini@konsulko.com> wrote:
>
> On Thu, Jan 19, 2023 at 09:54:29AM -0700, Simon Glass wrote:
> > Hi Sudeep,
> >
> > On Thu, 19 Jan 2023 at 09:46, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > >
> > > Hi Abdellatif,
> > >
> > > On Thu, Jan 19, 2023 at 04:31:57PM +0000, Abdellatif El Khlifi wrote:
> > > >
> > > > Hi Simon, Tom,
> > > >
> > > > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > > > undiscoverable base address.
> > > >
> > > > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > > > interfaces. The FF-A spec [1] describes this in details.
> > > >
> > > > Discovering means gathering information about the FF-A framework such as:
> > > > the FF-A version, supported features, secure partitions number and attributes.
> > > >
> > > > Please refer to the following paragraphs for more details: [2], [3], [4], [5]
> > > >
> > > > The core driver provided by this patchset implements the Setup and discovery interfaces
> > > > in addition to direct messaging.
> > > >
> > > > The driver provides ffa_bus_discover() API that allows to discover the FF-A bus
> > > > as described by the spec and in the FF-A driver readme [6].
> > > >
> > > > We expect and highly recommend FF-A users to always discover the FF-A bus using ffa_bus_discover() API.
> > > >
> > >
> > > Thanks for the details. But IIRC this discussion is not about the FF-A bus
> > > and device(partitions) discovery, but the support for FF-A itself. The
> > > discussion is about where to have a device node to represent the existence of
> > > FF-A support on a platform. If we are talking about individual partitions
> > > (devices) in the device tree, then that is pure stupidity as it goes out
> > > of since with the firmware the moment a partition is added or removed in
> > > the firmware.
> > >
> > > IIUC, the whole discussion was around whether to use FFA_VERSION as the
> > > discovery mechanism for existence of FF-A support on a platform or you
> > > have a device node to specify the same.
> >
> > No, with respect, that is not quite the situation here.
> >
> > >
> > > Just to be clear, even if it is decided to add a device node, the
> > > FFA_VERSION must be used to detect the presence of FF-A support and
> > > return error otherwise. DT node presence is just to satisfy the design
> > > and must be treated as no auto-confirmation for the presence of FF-A
> > > support. We are just arguing the device node presence is just redundant,
> > > but as mentioned before it is up to U-Boot community to make a call on
> > > what is best.
> >
> > U-Boot driver model design already supports this. You can have a
> > device that binds (from DT) but will not probe because it is not
> > present / wrong version. Perhaps this was missed in the conversion to
> > Linux:
> >
> > https://u-boot.readthedocs.io/en/latest/develop/driver-model/design.html#driver-lifecycle
> >
> > So there is nothing clever needed here at all and anything you do just
> > adds confusion and bad precedent.
>
> But it's also true that at run-time, within U-Boot, we can modify the
> device tree we have, with live tree yes? So, the whole series in
> question here can be done without modifying the base DT and getting in
> to the further discussions that doing so entails. The assertion is that
> the software discoverable bus here is sufficient to not need DT, so, OK,
> lets go.

One of the reasons that I find this all so frustrating is that it is
circular logic:

1. Device-tree bindings are controlled by Linux; U-Boot cannot upstream bindings
2. We can only have upstreamed bindings in any device tree

We have invented a whole u-boot.dtsi feature in U-Boot to hold
modifications from Linux. Board vendors have been suffering with this
for years.

It is not fair and it really needs to stop. I am doing what I can to
upstream some basic U-Boot bindings and I hope that will work and can
lead to a healthier relationship here.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 17:09                                                                               ` Sudeep Holla
@ 2023-01-19 17:21                                                                                 ` Tom Rini
  2023-01-19 17:22                                                                                 ` Simon Glass
  1 sibling, 0 replies; 478+ messages in thread
From: Tom Rini @ 2023-01-19 17:21 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Simon Glass, Abdellatif El Khlifi, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, ilias.apalodimas, u-boot

[-- Attachment #1: Type: text/plain, Size: 2232 bytes --]

On Thu, Jan 19, 2023 at 05:09:45PM +0000, Sudeep Holla wrote:
> On Thu, Jan 19, 2023 at 11:57:44AM -0500, Tom Rini wrote:
> >
> > But it's also true that at run-time, within U-Boot, we can modify the
> > device tree we have, with live tree yes? So, the whole series in
> > question here can be done without modifying the base DT and getting in
> > to the further discussions that doing so entails. The assertion is that
> > the software discoverable bus here is sufficient to not need DT, so, OK,
> > lets go.
> 
> OK, may be I am not up-to-date on the U-Boot. IIUC, the modifications
> done in the DT by U-Boot is mostly for consumption by the next stage
> loader/OS and not for self-consumption. But if it is for self consumption,
> then good. It helps especially for the subnodes(as Simon referred) or the
> partitions that can be discovered at run-time using FF-A interface.
> 
> As mentioned I am not again DT, it is just not needed and especially
> for subnodes it could result in inconsistency b/w what is in DT and
> what the firmware provides. As mentioned in previous response, having a
> simple node that Simon provided as example earlier is fine by me if that
> is the only option to make progress as I just feel it is redundant and
> one can say not scalable(but that is debatable again 😄).
> 
> In short, I am not concerned about having simple node, just don't like
> to see entire FF-A bus enumerated in DT as subnodes for reasons mentioned
> already.

So there's two parts to this discussion. The first of which has been, do
Simon and I agree with the direction of defining a software discoverable
bus rather than using device tree to describe it. To which the answer is
no, and also neither camp seems likely to convince the other. The second
part of the discussion is what can we practically do about it. To which
the answer is that I believe the live tree support (see
https://u-boot.readthedocs.io/en/latest/develop/driver-model/livetree.html)
should allow for the FF-A bus support to be integrated with U-Boot,
without having to add something to the base device tree.  And we can
evaluate down the line if our fears (or at least mine) were unfounded or
not.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 17:09                                                                               ` Sudeep Holla
  2023-01-19 17:21                                                                                 ` Tom Rini
@ 2023-01-19 17:22                                                                                 ` Simon Glass
  2023-01-20 11:17                                                                                   ` Sudeep Holla
  1 sibling, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-01-19 17:22 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, ilias.apalodimas, u-boot

Hi Sudeep,

On Thu, 19 Jan 2023 at 10:09, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Thu, Jan 19, 2023 at 11:57:44AM -0500, Tom Rini wrote:
> >
> > But it's also true that at run-time, within U-Boot, we can modify the
> > device tree we have, with live tree yes? So, the whole series in
> > question here can be done without modifying the base DT and getting in
> > to the further discussions that doing so entails. The assertion is that
> > the software discoverable bus here is sufficient to not need DT, so, OK,
> > lets go.
>
> OK, may be I am not up-to-date on the U-Boot. IIUC, the modifications
> done in the DT by U-Boot is mostly for consumption by the next stage
> loader/OS and not for self-consumption. But if it is for self consumption,
> then good. It helps especially for the subnodes(as Simon referred) or the
> partitions that can be discovered at run-time using FF-A interface.

It's really just dodging the issue though, because you need a
compatible string and you might as well add it to the DT in the source
as do it at runtime.

>
> As mentioned I am not again DT, it is just not needed and especially
> for subnodes it could result in inconsistency b/w what is in DT and
> what the firmware provides. As mentioned in previous response, having a
> simple node that Simon provided as example earlier is fine by me if that
> is the only option to make progress as I just feel it is redundant and
> one can say not scalable(but that is debatable again 😄).

Gosh, how many of these things are you going to add? I believe the
inconsistency argument is dealt with by the bind/probe explanation. It
may be redundant in Linux but I doubt it would hurt there either.

>
> In short, I am not concerned about having simple node, just don't like
> to see entire FF-A bus enumerated in DT as subnodes for reasons mentioned
> already.

Fair enough, and that is agreed on my side. I'll note that with PCI we
sometimes do add nodes in order to provide parameters to the driver,
there being no other sensible way to do this in U-Boot, for example:

https://github.com/u-boot/u-boot/blob/master/arch/x86/dts/chromebook_coral.dts#L183

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 17:21                                                                               ` Simon Glass
@ 2023-01-19 17:24                                                                                 ` Tom Rini
  2023-01-19 18:04                                                                                   ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-01-19 17:24 UTC (permalink / raw)
  To: Simon Glass
  Cc: Sudeep Holla, Abdellatif El Khlifi, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, ilias.apalodimas, u-boot

[-- Attachment #1: Type: text/plain, Size: 4597 bytes --]

On Thu, Jan 19, 2023 at 10:21:07AM -0700, Simon Glass wrote:
> Hi Tom,
> 
> On Thu, 19 Jan 2023 at 09:57, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Thu, Jan 19, 2023 at 09:54:29AM -0700, Simon Glass wrote:
> > > Hi Sudeep,
> > >
> > > On Thu, 19 Jan 2023 at 09:46, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > > >
> > > > Hi Abdellatif,
> > > >
> > > > On Thu, Jan 19, 2023 at 04:31:57PM +0000, Abdellatif El Khlifi wrote:
> > > > >
> > > > > Hi Simon, Tom,
> > > > >
> > > > > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > > > > undiscoverable base address.
> > > > >
> > > > > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > > > > interfaces. The FF-A spec [1] describes this in details.
> > > > >
> > > > > Discovering means gathering information about the FF-A framework such as:
> > > > > the FF-A version, supported features, secure partitions number and attributes.
> > > > >
> > > > > Please refer to the following paragraphs for more details: [2], [3], [4], [5]
> > > > >
> > > > > The core driver provided by this patchset implements the Setup and discovery interfaces
> > > > > in addition to direct messaging.
> > > > >
> > > > > The driver provides ffa_bus_discover() API that allows to discover the FF-A bus
> > > > > as described by the spec and in the FF-A driver readme [6].
> > > > >
> > > > > We expect and highly recommend FF-A users to always discover the FF-A bus using ffa_bus_discover() API.
> > > > >
> > > >
> > > > Thanks for the details. But IIRC this discussion is not about the FF-A bus
> > > > and device(partitions) discovery, but the support for FF-A itself. The
> > > > discussion is about where to have a device node to represent the existence of
> > > > FF-A support on a platform. If we are talking about individual partitions
> > > > (devices) in the device tree, then that is pure stupidity as it goes out
> > > > of since with the firmware the moment a partition is added or removed in
> > > > the firmware.
> > > >
> > > > IIUC, the whole discussion was around whether to use FFA_VERSION as the
> > > > discovery mechanism for existence of FF-A support on a platform or you
> > > > have a device node to specify the same.
> > >
> > > No, with respect, that is not quite the situation here.
> > >
> > > >
> > > > Just to be clear, even if it is decided to add a device node, the
> > > > FFA_VERSION must be used to detect the presence of FF-A support and
> > > > return error otherwise. DT node presence is just to satisfy the design
> > > > and must be treated as no auto-confirmation for the presence of FF-A
> > > > support. We are just arguing the device node presence is just redundant,
> > > > but as mentioned before it is up to U-Boot community to make a call on
> > > > what is best.
> > >
> > > U-Boot driver model design already supports this. You can have a
> > > device that binds (from DT) but will not probe because it is not
> > > present / wrong version. Perhaps this was missed in the conversion to
> > > Linux:
> > >
> > > https://u-boot.readthedocs.io/en/latest/develop/driver-model/design.html#driver-lifecycle
> > >
> > > So there is nothing clever needed here at all and anything you do just
> > > adds confusion and bad precedent.
> >
> > But it's also true that at run-time, within U-Boot, we can modify the
> > device tree we have, with live tree yes? So, the whole series in
> > question here can be done without modifying the base DT and getting in
> > to the further discussions that doing so entails. The assertion is that
> > the software discoverable bus here is sufficient to not need DT, so, OK,
> > lets go.
> 
> One of the reasons that I find this all so frustrating is that it is
> circular logic:
> 
> 1. Device-tree bindings are controlled by Linux; U-Boot cannot upstream bindings
> 2. We can only have upstreamed bindings in any device tree
> 
> We have invented a whole u-boot.dtsi feature in U-Boot to hold
> modifications from Linux. Board vendors have been suffering with this
> for years.
> 
> It is not fair and it really needs to stop. I am doing what I can to
> upstream some basic U-Boot bindings and I hope that will work and can
> lead to a healthier relationship here.

Yes, but this is a problem outside of that scope. The argument here is
that one does not need a device tree node to work. So lets see just how
clean and nice the code can be without what you and I have been
insisting would lead to the cleanest result.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 17:24                                                                                 ` Tom Rini
@ 2023-01-19 18:04                                                                                   ` Simon Glass
  2023-01-20 10:52                                                                                     ` Sudeep Holla
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-01-19 18:04 UTC (permalink / raw)
  To: Tom Rini
  Cc: Sudeep Holla, Abdellatif El Khlifi, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, ilias.apalodimas, u-boot

Hi Tom,

On Thu, 19 Jan 2023 at 10:24, Tom Rini <trini@konsulko.com> wrote:
>
> On Thu, Jan 19, 2023 at 10:21:07AM -0700, Simon Glass wrote:
> > Hi Tom,
> >
> > On Thu, 19 Jan 2023 at 09:57, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Thu, Jan 19, 2023 at 09:54:29AM -0700, Simon Glass wrote:
> > > > Hi Sudeep,
> > > >
> > > > On Thu, 19 Jan 2023 at 09:46, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > > > >
> > > > > Hi Abdellatif,
> > > > >
> > > > > On Thu, Jan 19, 2023 at 04:31:57PM +0000, Abdellatif El Khlifi wrote:
> > > > > >
> > > > > > Hi Simon, Tom,
> > > > > >
> > > > > > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > > > > > undiscoverable base address.
> > > > > >
> > > > > > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > > > > > interfaces. The FF-A spec [1] describes this in details.
> > > > > >
> > > > > > Discovering means gathering information about the FF-A framework such as:
> > > > > > the FF-A version, supported features, secure partitions number and attributes.
> > > > > >
> > > > > > Please refer to the following paragraphs for more details: [2], [3], [4], [5]
> > > > > >
> > > > > > The core driver provided by this patchset implements the Setup and discovery interfaces
> > > > > > in addition to direct messaging.
> > > > > >
> > > > > > The driver provides ffa_bus_discover() API that allows to discover the FF-A bus
> > > > > > as described by the spec and in the FF-A driver readme [6].
> > > > > >
> > > > > > We expect and highly recommend FF-A users to always discover the FF-A bus using ffa_bus_discover() API.
> > > > > >
> > > > >
> > > > > Thanks for the details. But IIRC this discussion is not about the FF-A bus
> > > > > and device(partitions) discovery, but the support for FF-A itself. The
> > > > > discussion is about where to have a device node to represent the existence of
> > > > > FF-A support on a platform. If we are talking about individual partitions
> > > > > (devices) in the device tree, then that is pure stupidity as it goes out
> > > > > of since with the firmware the moment a partition is added or removed in
> > > > > the firmware.
> > > > >
> > > > > IIUC, the whole discussion was around whether to use FFA_VERSION as the
> > > > > discovery mechanism for existence of FF-A support on a platform or you
> > > > > have a device node to specify the same.
> > > >
> > > > No, with respect, that is not quite the situation here.
> > > >
> > > > >
> > > > > Just to be clear, even if it is decided to add a device node, the
> > > > > FFA_VERSION must be used to detect the presence of FF-A support and
> > > > > return error otherwise. DT node presence is just to satisfy the design
> > > > > and must be treated as no auto-confirmation for the presence of FF-A
> > > > > support. We are just arguing the device node presence is just redundant,
> > > > > but as mentioned before it is up to U-Boot community to make a call on
> > > > > what is best.
> > > >
> > > > U-Boot driver model design already supports this. You can have a
> > > > device that binds (from DT) but will not probe because it is not
> > > > present / wrong version. Perhaps this was missed in the conversion to
> > > > Linux:
> > > >
> > > > https://u-boot.readthedocs.io/en/latest/develop/driver-model/design.html#driver-lifecycle
> > > >
> > > > So there is nothing clever needed here at all and anything you do just
> > > > adds confusion and bad precedent.
> > >
> > > But it's also true that at run-time, within U-Boot, we can modify the
> > > device tree we have, with live tree yes? So, the whole series in
> > > question here can be done without modifying the base DT and getting in
> > > to the further discussions that doing so entails. The assertion is that
> > > the software discoverable bus here is sufficient to not need DT, so, OK,
> > > lets go.
> >
> > One of the reasons that I find this all so frustrating is that it is
> > circular logic:
> >
> > 1. Device-tree bindings are controlled by Linux; U-Boot cannot upstream bindings
> > 2. We can only have upstreamed bindings in any device tree
> >
> > We have invented a whole u-boot.dtsi feature in U-Boot to hold
> > modifications from Linux. Board vendors have been suffering with this
> > for years.
> >
> > It is not fair and it really needs to stop. I am doing what I can to
> > upstream some basic U-Boot bindings and I hope that will work and can
> > lead to a healthier relationship here.
>
> Yes, but this is a problem outside of that scope. The argument here is
> that one does not need a device tree node to work. So lets see just how
> clean and nice the code can be without what you and I have been
> insisting would lead to the cleanest result.

Well we already have the code, right...?

The entire device tree is optional. We could just use platform data or
even C function calls to set up devices. We could call a C function
for each board which builds a device tree early in boot. Etc... As I
remember it, no one wanted to use DT and it was only Linus Torvalds'
refusal to accept another ARM pull request that made people move away
from platform data and other ad-hoc mechanisms. I'll note that U-Boot
adopted DT on ARM in 2011, the same year as Linux [1] [2]. Since then
huge strides have been made in many ways, e.g. loads of useful
bindings and Rob Herring's validation stuff.

IMO the problem here is exactly because of the point I mentioned. I
suspect the reason no one wants to add a compatible string for the
top-level FF-A device is that it will be rejected by Linux and they
don't want another case of PTSD (I am willing to take that on if it
helps). I'm sorry that we are in this situation, but it is not going
to be fixed by ignoring the problem. It is causing all sorts of
work-arounds [3], is bad for project interoperability (and therefore
the open source industry as a whole), wastes a huge amount of time in
discussion and gives device tree a bad name[4]. It really, really
needs to stop.

Can we all agree to work together on this and see device tree as a
shared technology and resource, across firmware and OS? Could this be
the last thread on this topic?

Regards,
Simon

[1] U-Boot 45ba8077f3e ("fdt: ARM: Add device tree control of U-Boot
(CONFIG_OF_CONTROL)")
[2] Linux 9eb8f6743b076b ("arm/dt: Allow CONFIG_OF on ARM")
[3] I won't attempt to list them but I could probably find >100
separate U-Boot mailing-list threads trying to work around the
inability to have U-Boot bindings upstream
[4] I suspect it is a major reason why ARM adopted ACPI on servers

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 16:41                                                                         ` Simon Glass
  2023-01-19 16:43                                                                           ` Tom Rini
  2023-01-19 16:56                                                                           ` Sudeep Holla
@ 2023-01-19 18:11                                                                           ` Rob Herring
  2023-01-20 10:33                                                                             ` Sudeep Holla
  2023-01-20 22:04                                                                             ` Simon Glass
  2 siblings, 2 replies; 478+ messages in thread
From: Rob Herring @ 2023-01-19 18:11 UTC (permalink / raw)
  To: Simon Glass
  Cc: Abdellatif El Khlifi, trini, achin.gupta, xueliang.zhong,
	Drew.Reed, sudeep.holla, jens.wiklander, ilias.apalodimas, nd,
	u-boot

On Thu, Jan 19, 2023 at 10:41 AM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Abdellatif,
>
> On Thu, 19 Jan 2023 at 09:32, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > On Wed, Jan 18, 2023 at 08:59:32AM -0500, Tom Rini wrote:
> > > On Wed, Jan 18, 2023 at 01:46:54PM +0000, Sudeep Holla wrote:
> > > > On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > >
> > > > > I guess the problem comes down to, can we have one discovery method that
> > > > > everyone shares, or do we have to let everyone invent a new discovery
> > > > > method every time?
> > > >
> > > >
> > > > No one needs to invent any discovery method every time if the firmware
> > > > specification
> > > > provides one and as Rob mentioned many times in the thread, all new firmware
> > > > specification must provide one and we are trying to make sure that is
> > > > the case with all new
> > > > specs from Arm.
> > > >
> > > >
> > > > > FF-A, Op-tee, U-Boot, coreboot, barebox (and
> > > > > everyone else I'm unintentionally forgetting) could just discover these
> > > > > things via device tree.
> > > >
> > > >
> > > > I leave that to the individual projects to decide and agree but
> > > > fundamentally if
> > > > the specification provides a way to discover, not sure why we are even
> > > > discussing
> > > > an alternative method here.
> > > >
> > > >
> > > > > Or, we could all write our own code to perform
> > > > > the discovery.
> > > >
> > > >
> > > > For what reason ? I can understand if there is no discovery mechanism but
> > > > that's not the
> > > > case in $subject.
> > > >
> > > >
> > > > > And when RISC-V comes along with similar functionality,
> > > > > we could probe their device tree and see they've implemented the same
> > > > > concept, but a little differently, but still have the discovery portion
> > > > > be in the device tree. To which it sounds like your answer is "not in
> > > > > the device tree".
> > > > >
> > > >
> > > > I see U-boot seem to have made a decision to create DT node for each and
> > > > everything
> > > > that needs to be added to DM which seems bit unfortunate but I don't
> > > > understand the
> > > > history/motive/background for it but I respect the decision if it is
> > > > already made.
> > > >
> > > > These firmware interfaces are standard on all Arm platforms and can be
> > > > discovered
> > > > based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
> > > > addition of DT nodes for all the f/w i/f on all the platforms that need the
> > > > support when
> > > > one can be just discovered.
> > > >
> > > > Sorry for the sudden appearance on this thread, I was avoiding getting into
> > > > this but thought
> > > > I will at least express my opinion and also the way the firmware
> > > > specifications from Arm is
> > > > expected to be evolved from now on. With that I will leave it to you and
> > > > other U-boot
> > > > maintainers and the community in general to decide the right course in this
> > > > case.
> > >
> > > To be clear, if the position is that "this is what everyone else will
> > > use, really" then yes, we'll follow this in U-Boot.
> >
> > Hi Simon, Tom,
> >
> > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > undiscoverable base address.
> >
> > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > interfaces. The FF-A spec [1] describes this in details.
>
> Can you add a DT node for the 'FF-A SW interfaces' and attach some
> sort of top-level driver to that? Perhaps simple-bus, or your own
> thing? You don't need to add compatible strings for subnodes (devices
> that are discoverable within that).

We already have that. It's just called 'arm,psci'. FF-A is not the
top-level thing. SMCCC is. That's unfortunately called PSCI in DT
because SMCCC grew out of PSCI. Evolution is ugly...

It's like this:

SMCCC
  +--PSCI
  +--TRNG
  +--FF-A
  +--SCMI (sometimes)
  +--OP-TEE
  +--...Whatever Arm comes up with next...

Rob

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 16:56                                                                           ` Sudeep Holla
@ 2023-01-20  9:56                                                                             ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-01-20  9:56 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: trini, achin.gupta, xueliang.zhong, Drew.Reed, robh,
	jens.wiklander, ilias.apalodimas, nd, u-boot, sjg

On Thu, Jan 19, 2023 at 04:56:09PM +0000, Sudeep Holla wrote:
> Hi Simon,
> 
> (sorry we just crossed the emails)
> 
> On Thu, Jan 19, 2023 at 09:41:12AM -0700, Simon Glass wrote:
> >
> > Can you add a DT node for the 'FF-A SW interfaces' and attach some
> > sort of top-level driver to that? Perhaps simple-bus, or your own
> > thing? You don't need to add compatible strings for subnodes (devices
> > that are discoverable within that).
> >
> 
> Thanks for putting this nicely. I just wrote the same thing probably in
> not so simpler way. But I agree with you as Abdellatif last email talks
> more around sub-nodes or child device nodes (devices that are discoverable
> within that)

Hi Sudeep,

A gentle reminder about what has been said in my last reply:

I didn't talk about sub-nodes or child nodes. The FF-A driver in u-boot doesn't do that.

In this patchset, only 1 device is created: The FF-A bus device (arm_ffa).

The discovery done by the driver queries all the discovery interfaces described in Chapter 8 of the spec, not just FFA_VERSION.

The discovery interfaces are queried in this order:

    FFA_VERSION.
    FFA_ID_GET.
    FFA_FEATURES.
    FFA_PARTITION_INFO_GET.

Setup interfaces are used during discovery as well.

If one of these interfaces fail, the discovery fails.

The discovery from this patchset point of view is the discovery process involving the interfaces above.

Cheers

> 
> > If you don't want to submit the compatible string to Linux, I will do
> > it. If it has to have a 'u-boot,' prefix then so be it, but I don't
> > see why that is necessary, since Linux can ignore it if it likes.
> >
> > We have been talking about this for far too long, IMO. Would you like
> > me to send a patch? It is something like this:
> >
> > ff-a {
> >     compatible = "arm,ff-a";
> > };
> >
> 
> Makes sense if DT node is the only way. It should be as simple as this
> and presence of this must not imply presence of FF-A feature on the
> platform. The driver must check using FFA_VERSION
> 
> > >
> > > Discovering means gathering information about the FF-A framework such as:
> > > the FF-A version, supported features, secure partitions number and attributes.
> > >
> > > Please refer to the following paragraphs for more details: [2], [3], [4], [5]
> > >
> > > The core driver provided by this patchset implements the Setup and discovery interfaces
> > > in addition to direct messaging.
> > >
> > > The driver provides ffa_bus_discover() API that allows to discover the FF-A bus
> > > as described by the spec and in the FF-A driver readme [6].
> > >
> > > We expect and highly recommend FF-A users to always discover the FF-A bus using ffa_bus_discover() API.
> > >
> > > A use case is provided which is the EFI MM communication [7].
> > >
> > > ffa_bus_discover() does the following:
> > >
> > > - creates, binds and probes the arm_ffa device
> > > - at probe level, discovery FF-A interfaces are called to try to discover the FF-A framework
> > > - when all discovery interfaces succeed, probing is successful and FF-A bus is ready to use
> > > - if one of the discovery interfaces fails, the arm_ffa device is removed from the DM and
> > >   FF-A bus can not be used
> >
> > This is not how things are supposed to work in U-Boot. Please read the
> > documentation which is here:
> >
> > https://u-boot.readthedocs.io/en/latest/develop/driver-model/index.html
> >
> > So referencing above:
> >
> > 1, No, the binding of the ff-a device should happen automatically from the DT
> > 2. probing ff-a causes the other devices to be bound (as with PCI,
> > USB, every other bus in U-Boot)
> > 3. Yes
> > 4. No, you must not unbind it. It just sits there unprobed and cannot
> > be used. We might want to have a command that looks at what is wrong
> > with it. Probing the device should produce an error, as with every
> > other device in U-Boot
> >
> 
> Agreed on all points(assuming DT way here). Especially the last point,
> there is no point is rolling back if one partion/device initialisation
> fails or is not bound.
> 
> --
> Regards,
> Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 18:11                                                                           ` Rob Herring
@ 2023-01-20 10:33                                                                             ` Sudeep Holla
  2023-01-20 22:04                                                                             ` Simon Glass
  1 sibling, 0 replies; 478+ messages in thread
From: Sudeep Holla @ 2023-01-20 10:33 UTC (permalink / raw)
  To: Rob Herring
  Cc: Simon Glass, Abdellatif El Khlifi, trini, achin.gupta,
	xueliang.zhong, Sudeep Holla, Drew.Reed, jens.wiklander,
	ilias.apalodimas, nd, u-boot

On Thu, Jan 19, 2023 at 12:11:34PM -0600, Rob Herring wrote:
> On Thu, Jan 19, 2023 at 10:41 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Can you add a DT node for the 'FF-A SW interfaces' and attach some
> > sort of top-level driver to that? Perhaps simple-bus, or your own
> > thing? You don't need to add compatible strings for subnodes (devices
> > that are discoverable within that).
>
> We already have that. It's just called 'arm,psci'. FF-A is not the
> top-level thing. SMCCC is. That's unfortunately called PSCI in DT
> because SMCCC grew out of PSCI. Evolution is ugly...
>
> It's like this:
>
> SMCCC
>   +--PSCI
>   +--TRNG
>   +--FF-A
>   +--SCMI (sometimes)
>   +--OP-TEE
>   +--...Whatever Arm comes up with next...
>

Thanks Rob for the nice description.

Hi Simon,

Though SMCCC and PSCI are kind of swapped in reality like Rob mentioned
while referring to the ugly evolution, we are trying to stick with PSCI
node and discovery other features dynamically in the kernel. Hope the
reasons for not defining the extra unnecessary bindings for FF-A is clear
now.

There are couple of other bindings IIRC, one being for the OPTEE for example
which again could have been avoid if we had better idea on how these SMCCC and
its users would have evolved.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 18:04                                                                                   ` Simon Glass
@ 2023-01-20 10:52                                                                                     ` Sudeep Holla
  0 siblings, 0 replies; 478+ messages in thread
From: Sudeep Holla @ 2023-01-20 10:52 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, Sudeep Holla, ilias.apalodimas,
	u-boot

Hi Simon,

On Thu, Jan 19, 2023 at 11:04:16AM -0700, Simon Glass wrote:
[...]

>
> Well we already have the code, right...?
>

Correct, that what we would like to see.

> The entire device tree is optional. We could just use platform data or
> even C function calls to set up devices. We could call a C function
> for each board which builds a device tree early in boot. Etc... As I
> remember it, no one wanted to use DT and it was only Linus Torvalds'
> refusal to accept another ARM pull request that made people move away
> from platform data and other ad-hoc mechanisms. I'll note that U-Boot
> adopted DT on ARM in 2011, the same year as Linux [1] [2]. Since then
> huge strides have been made in many ways, e.g. loads of useful
> bindings and Rob Herring's validation stuff.
>

OK here is where I differ from your understanding. DT for mainly to replace
platform specific data. And though firmware is *platform specific*,
the firmware interface itself is not and can be compared to architecture
features. Do we define all Arm architecture specific features in the
DT, the answer is clearly no, unless there is something missed in the
architecture specification and too late to add anything to support
platforms in the wild.

Similarly, the some of these standard firmware interfaces are to avoid
such platform description in DT or ACPI. There are self discoverable like
some of the architecture features. It is just in software rather than the
hardware.

> IMO the problem here is exactly because of the point I mentioned. I
> suspect the reason no one wants to add a compatible string for the
> top-level FF-A device is that it will be rejected by Linux and they
> don't want another case of PTSD (I am willing to take that on if it
> helps). I'm sorry that we are in this situation, but it is not going
> to be fixed by ignoring the problem. It is causing all sorts of
> work-arounds [3], is bad for project interoperability (and therefore
> the open source industry as a whole), wastes a huge amount of time in
> discussion and gives device tree a bad name[4]. It really, really
> needs to stop.

I am not sure if that is the reason for ACPI adoption TBH. IMO both
have their own advantage and disadvantage. The idea is to try to minimise
the deviation between the two(not on a wider scope though). The firmware
interfaces like FF-A avoids the needs for any description of the feature
in DT or ACPI all together and hence avoids any such deviation problems.

>
> Can we all agree to work together on this and see device tree as a
> shared technology and resource, across firmware and OS? Could this be
> the last thread on this topic?
>

With the mention of ACPI now I just can't think how do you propose to
use DT as shared tech/ resource across f/w and OS when ACPI is used.

For sure if something is not discoverable, they need to be described in
DT and hence in ACPI too, but FF-A is not one such feature and I have no
justification to add it in ACPI other than "DT has it, so lets add even
if it is unnecessary".

In summary, look at FF-A as software architecture feature that can be
discovered and not as a platform specific feature that needs platform
specific data from DT or ACPI.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 17:22                                                                                 ` Simon Glass
@ 2023-01-20 11:17                                                                                   ` Sudeep Holla
  2023-01-23 16:32                                                                                     ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Sudeep Holla @ 2023-01-20 11:17 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, Sudeep Holla, ilias.apalodimas,
	u-boot

On Thu, Jan 19, 2023 at 10:22:07AM -0700, Simon Glass wrote:
> Hi Sudeep,
> 
> On Thu, 19 Jan 2023 at 10:09, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > On Thu, Jan 19, 2023 at 11:57:44AM -0500, Tom Rini wrote:
> > >
> > > But it's also true that at run-time, within U-Boot, we can modify the
> > > device tree we have, with live tree yes? So, the whole series in
> > > question here can be done without modifying the base DT and getting in
> > > to the further discussions that doing so entails. The assertion is that
> > > the software discoverable bus here is sufficient to not need DT, so, OK,
> > > lets go.
> >
> > OK, may be I am not up-to-date on the U-Boot. IIUC, the modifications
> > done in the DT by U-Boot is mostly for consumption by the next stage
> > loader/OS and not for self-consumption. But if it is for self consumption,
> > then good. It helps especially for the subnodes(as Simon referred) or the
> > partitions that can be discovered at run-time using FF-A interface.
> 
> It's really just dodging the issue though, because you need a
> compatible string and you might as well add it to the DT in the source
> as do it at runtime.
>

Well that is one of the argument assuming DT node is a must. But adding
DT node requirement when it is not needed can be seen an issue itself if
one has to play devil's advocate here.

> >
> > As mentioned I am not again DT, it is just not needed and especially
> > for subnodes it could result in inconsistency b/w what is in DT and
> > what the firmware provides. As mentioned in previous response, having a
> > simple node that Simon provided as example earlier is fine by me if that
> > is the only option to make progress as I just feel it is redundant and
> > one can say not scalable(but that is debatable again 😄).
>
> Gosh, how many of these things are you going to add? I believe the
> inconsistency argument is dealt with by the bind/probe explanation. It
> may be redundant in Linux but I doubt it would hurt there either.
>

Not really. Currently the number of partitions is static and all of them
are bundled into on or few binaries. But we could have dynamic partitions
in the future. More over it is pain to update the DT for each possible
configuration especially during development where you want to experiment
things around. Having to deal with the DT for every small change in the
config is just annoying. Yes one could have universal list of partitions
and defer it to be dealt at probe/bind, but not sure if it is possible
to have such a universal list during development. We may have it handy
for production but we also want to ease development here.

In short, I have had quite a lot of issues with DT and firmware
inconsistency due to duplication of same data at the beginning and the
things diverged. So I am simply not ready to go back there and I am sure
quite a few in the kernel community have their fingers bitten because of
such inconsistency created by *unnecessary static addition of data* to
the DT. So, let me be clear, I wouldn't use the information from the
DT if I can get more accurate one dynamically from the firmware in the
kernel driver.

-- 
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-19 18:11                                                                           ` Rob Herring
  2023-01-20 10:33                                                                             ` Sudeep Holla
@ 2023-01-20 22:04                                                                             ` Simon Glass
  2023-01-23 15:13                                                                               ` Rob Herring
  1 sibling, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-01-20 22:04 UTC (permalink / raw)
  To: Rob Herring
  Cc: Abdellatif El Khlifi, trini, achin.gupta, xueliang.zhong,
	Drew.Reed, sudeep.holla, jens.wiklander, ilias.apalodimas, nd,
	u-boot

Hi Rob,

On Thu, 19 Jan 2023 at 11:11, Rob Herring <robh@kernel.org> wrote:
>
> On Thu, Jan 19, 2023 at 10:41 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Abdellatif,
> >
> > On Thu, 19 Jan 2023 at 09:32, Abdellatif El Khlifi
> > <abdellatif.elkhlifi@arm.com> wrote:
> > >
> > > On Wed, Jan 18, 2023 at 08:59:32AM -0500, Tom Rini wrote:
> > > > On Wed, Jan 18, 2023 at 01:46:54PM +0000, Sudeep Holla wrote:
> > > > > On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:
> > > > >
> > > > > >
> > > > > > I guess the problem comes down to, can we have one discovery method that
> > > > > > everyone shares, or do we have to let everyone invent a new discovery
> > > > > > method every time?
> > > > >
> > > > >
> > > > > No one needs to invent any discovery method every time if the firmware
> > > > > specification
> > > > > provides one and as Rob mentioned many times in the thread, all new firmware
> > > > > specification must provide one and we are trying to make sure that is
> > > > > the case with all new
> > > > > specs from Arm.
> > > > >
> > > > >
> > > > > > FF-A, Op-tee, U-Boot, coreboot, barebox (and
> > > > > > everyone else I'm unintentionally forgetting) could just discover these
> > > > > > things via device tree.
> > > > >
> > > > >
> > > > > I leave that to the individual projects to decide and agree but
> > > > > fundamentally if
> > > > > the specification provides a way to discover, not sure why we are even
> > > > > discussing
> > > > > an alternative method here.
> > > > >
> > > > >
> > > > > > Or, we could all write our own code to perform
> > > > > > the discovery.
> > > > >
> > > > >
> > > > > For what reason ? I can understand if there is no discovery mechanism but
> > > > > that's not the
> > > > > case in $subject.
> > > > >
> > > > >
> > > > > > And when RISC-V comes along with similar functionality,
> > > > > > we could probe their device tree and see they've implemented the same
> > > > > > concept, but a little differently, but still have the discovery portion
> > > > > > be in the device tree. To which it sounds like your answer is "not in
> > > > > > the device tree".
> > > > > >
> > > > >
> > > > > I see U-boot seem to have made a decision to create DT node for each and
> > > > > everything
> > > > > that needs to be added to DM which seems bit unfortunate but I don't
> > > > > understand the
> > > > > history/motive/background for it but I respect the decision if it is
> > > > > already made.
> > > > >
> > > > > These firmware interfaces are standard on all Arm platforms and can be
> > > > > discovered
> > > > > based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
> > > > > addition of DT nodes for all the f/w i/f on all the platforms that need the
> > > > > support when
> > > > > one can be just discovered.
> > > > >
> > > > > Sorry for the sudden appearance on this thread, I was avoiding getting into
> > > > > this but thought
> > > > > I will at least express my opinion and also the way the firmware
> > > > > specifications from Arm is
> > > > > expected to be evolved from now on. With that I will leave it to you and
> > > > > other U-boot
> > > > > maintainers and the community in general to decide the right course in this
> > > > > case.
> > > >
> > > > To be clear, if the position is that "this is what everyone else will
> > > > use, really" then yes, we'll follow this in U-Boot.
> > >
> > > Hi Simon, Tom,
> > >
> > > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > > undiscoverable base address.
> > >
> > > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > > interfaces. The FF-A spec [1] describes this in details.
> >
> > Can you add a DT node for the 'FF-A SW interfaces' and attach some
> > sort of top-level driver to that? Perhaps simple-bus, or your own
> > thing? You don't need to add compatible strings for subnodes (devices
> > that are discoverable within that).
>
> We already have that. It's just called 'arm,psci'. FF-A is not the
> top-level thing. SMCCC is. That's unfortunately called PSCI in DT
> because SMCCC grew out of PSCI. Evolution is ugly...
>
> It's like this:
>
> SMCCC
>   +--PSCI
>   +--TRNG
>   +--FF-A
>   +--SCMI (sometimes)
>   +--OP-TEE
>   +--...Whatever Arm comes up with next...

OK well that sounds OK.

So what is the problem here? We have an SMCCC top-level thing in the
DT and everything else can be bound from that, right? Are people on
this thread not aware of this...or am I still missing something?

Can you point to the SMCCC driver in U-Boot? Is this
bind_smccc_features(), i.w.c. it looks like it does what I want...why
does this thread exist?

So confused...:-)

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-20 22:04                                                                             ` Simon Glass
@ 2023-01-23 15:13                                                                               ` Rob Herring
  2023-01-23 16:32                                                                                 ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Rob Herring @ 2023-01-23 15:13 UTC (permalink / raw)
  To: Simon Glass
  Cc: Abdellatif El Khlifi, trini, achin.gupta, xueliang.zhong,
	Drew.Reed, sudeep.holla, jens.wiklander, ilias.apalodimas, nd,
	u-boot

On Fri, Jan 20, 2023 at 4:04 PM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Rob,
>
> On Thu, 19 Jan 2023 at 11:11, Rob Herring <robh@kernel.org> wrote:
> >
> > On Thu, Jan 19, 2023 at 10:41 AM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Abdellatif,
> > >
> > > On Thu, 19 Jan 2023 at 09:32, Abdellatif El Khlifi
> > > <abdellatif.elkhlifi@arm.com> wrote:
> > > >
> > > > On Wed, Jan 18, 2023 at 08:59:32AM -0500, Tom Rini wrote:
> > > > > On Wed, Jan 18, 2023 at 01:46:54PM +0000, Sudeep Holla wrote:
> > > > > > On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:
> > > > > >
> > > > > > >
> > > > > > > I guess the problem comes down to, can we have one discovery method that
> > > > > > > everyone shares, or do we have to let everyone invent a new discovery
> > > > > > > method every time?
> > > > > >
> > > > > >
> > > > > > No one needs to invent any discovery method every time if the firmware
> > > > > > specification
> > > > > > provides one and as Rob mentioned many times in the thread, all new firmware
> > > > > > specification must provide one and we are trying to make sure that is
> > > > > > the case with all new
> > > > > > specs from Arm.
> > > > > >
> > > > > >
> > > > > > > FF-A, Op-tee, U-Boot, coreboot, barebox (and
> > > > > > > everyone else I'm unintentionally forgetting) could just discover these
> > > > > > > things via device tree.
> > > > > >
> > > > > >
> > > > > > I leave that to the individual projects to decide and agree but
> > > > > > fundamentally if
> > > > > > the specification provides a way to discover, not sure why we are even
> > > > > > discussing
> > > > > > an alternative method here.
> > > > > >
> > > > > >
> > > > > > > Or, we could all write our own code to perform
> > > > > > > the discovery.
> > > > > >
> > > > > >
> > > > > > For what reason ? I can understand if there is no discovery mechanism but
> > > > > > that's not the
> > > > > > case in $subject.
> > > > > >
> > > > > >
> > > > > > > And when RISC-V comes along with similar functionality,
> > > > > > > we could probe their device tree and see they've implemented the same
> > > > > > > concept, but a little differently, but still have the discovery portion
> > > > > > > be in the device tree. To which it sounds like your answer is "not in
> > > > > > > the device tree".
> > > > > > >
> > > > > >
> > > > > > I see U-boot seem to have made a decision to create DT node for each and
> > > > > > everything
> > > > > > that needs to be added to DM which seems bit unfortunate but I don't
> > > > > > understand the
> > > > > > history/motive/background for it but I respect the decision if it is
> > > > > > already made.
> > > > > >
> > > > > > These firmware interfaces are standard on all Arm platforms and can be
> > > > > > discovered
> > > > > > based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
> > > > > > addition of DT nodes for all the f/w i/f on all the platforms that need the
> > > > > > support when
> > > > > > one can be just discovered.
> > > > > >
> > > > > > Sorry for the sudden appearance on this thread, I was avoiding getting into
> > > > > > this but thought
> > > > > > I will at least express my opinion and also the way the firmware
> > > > > > specifications from Arm is
> > > > > > expected to be evolved from now on. With that I will leave it to you and
> > > > > > other U-boot
> > > > > > maintainers and the community in general to decide the right course in this
> > > > > > case.
> > > > >
> > > > > To be clear, if the position is that "this is what everyone else will
> > > > > use, really" then yes, we'll follow this in U-Boot.
> > > >
> > > > Hi Simon, Tom,
> > > >
> > > > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > > > undiscoverable base address.
> > > >
> > > > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > > > interfaces. The FF-A spec [1] describes this in details.
> > >
> > > Can you add a DT node for the 'FF-A SW interfaces' and attach some
> > > sort of top-level driver to that? Perhaps simple-bus, or your own
> > > thing? You don't need to add compatible strings for subnodes (devices
> > > that are discoverable within that).
> >
> > We already have that. It's just called 'arm,psci'. FF-A is not the
> > top-level thing. SMCCC is. That's unfortunately called PSCI in DT
> > because SMCCC grew out of PSCI. Evolution is ugly...
> >
> > It's like this:
> >
> > SMCCC
> >   +--PSCI
> >   +--TRNG
> >   +--FF-A
> >   +--SCMI (sometimes)
> >   +--OP-TEE
> >   +--...Whatever Arm comes up with next...
>
> OK well that sounds OK.
>
> So what is the problem here? We have an SMCCC top-level thing in the
> DT and everything else can be bound from that, right? Are people on
> this thread not aware of this...or am I still missing something?
>
> Can you point to the SMCCC driver in U-Boot? Is this
> bind_smccc_features(), i.w.c. it looks like it does what I want...why
> does this thread exist?

I imagine the u-boot structure for all this has evolved like the
bindings where each feature was developed independently. From my brief
look at it, initialization of all the above features would need to be
reworked to work as described.

Rob

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-20 11:17                                                                                   ` Sudeep Holla
@ 2023-01-23 16:32                                                                                     ` Simon Glass
  2023-01-24 11:30                                                                                       ` Sudeep Holla
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-01-23 16:32 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, ilias.apalodimas, u-boot

Hi Sudeep,

On Fri, 20 Jan 2023 at 04:17, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> On Thu, Jan 19, 2023 at 10:22:07AM -0700, Simon Glass wrote:
> > Hi Sudeep,
> >
> > On Thu, 19 Jan 2023 at 10:09, Sudeep Holla <sudeep.holla@arm.com> wrote:
> > >
> > > On Thu, Jan 19, 2023 at 11:57:44AM -0500, Tom Rini wrote:
> > > >
> > > > But it's also true that at run-time, within U-Boot, we can modify the
> > > > device tree we have, with live tree yes? So, the whole series in
> > > > question here can be done without modifying the base DT and getting in
> > > > to the further discussions that doing so entails. The assertion is that
> > > > the software discoverable bus here is sufficient to not need DT, so, OK,
> > > > lets go.
> > >
> > > OK, may be I am not up-to-date on the U-Boot. IIUC, the modifications
> > > done in the DT by U-Boot is mostly for consumption by the next stage
> > > loader/OS and not for self-consumption. But if it is for self consumption,
> > > then good. It helps especially for the subnodes(as Simon referred) or the
> > > partitions that can be discovered at run-time using FF-A interface.
> >
> > It's really just dodging the issue though, because you need a
> > compatible string and you might as well add it to the DT in the source
> > as do it at runtime.
> >
>
> Well that is one of the argument assuming DT node is a must. But adding
> DT node requirement when it is not needed can be seen an issue itself if
> one has to play devil's advocate here.
>
> > >
> > > As mentioned I am not again DT, it is just not needed and especially
> > > for subnodes it could result in inconsistency b/w what is in DT and
> > > what the firmware provides. As mentioned in previous response, having a
> > > simple node that Simon provided as example earlier is fine by me if that
> > > is the only option to make progress as I just feel it is redundant and
> > > one can say not scalable(but that is debatable again 😄).
> >
> > Gosh, how many of these things are you going to add? I believe the
> > inconsistency argument is dealt with by the bind/probe explanation. It
> > may be redundant in Linux but I doubt it would hurt there either.
> >
>
> Not really. Currently the number of partitions is static and all of them
> are bundled into on or few binaries. But we could have dynamic partitions
> in the future. More over it is pain to update the DT for each possible
> configuration especially during development where you want to experiment
> things around. Having to deal with the DT for every small change in the
> config is just annoying. Yes one could have universal list of partitions
> and defer it to be dealt at probe/bind, but not sure if it is possible
> to have such a universal list during development. We may have it handy
> for production but we also want to ease development here.
>
> In short, I have had quite a lot of issues with DT and firmware
> inconsistency due to duplication of same data at the beginning and the
> things diverged. So I am simply not ready to go back there and I am sure
> quite a few in the kernel community have their fingers bitten because of
> such inconsistency created by *unnecessary static addition of data* to
> the DT. So, let me be clear, I wouldn't use the information from the
> DT if I can get more accurate one dynamically from the firmware in the
> kernel driver.

I'd like to see DT defined across firmware and OS, not just be a Linux
thing. It is a better approach than having little fiefdoms everywhere
with their own config mechanisms.

It seems that you have lots of build-time config in the ARM
components. I suggest looking at how you can move this to runtime
config, if you are not planning to upstream the functionality to
U-Boot.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-23 15:13                                                                               ` Rob Herring
@ 2023-01-23 16:32                                                                                 ` Simon Glass
  2023-01-24 15:56                                                                                   ` Abdellatif El Khlifi
  2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  0 siblings, 2 replies; 478+ messages in thread
From: Simon Glass @ 2023-01-23 16:32 UTC (permalink / raw)
  To: Rob Herring
  Cc: Abdellatif El Khlifi, trini, achin.gupta, xueliang.zhong,
	Drew.Reed, sudeep.holla, jens.wiklander, ilias.apalodimas, nd,
	u-boot

Hi Rob,

On Mon, 23 Jan 2023 at 08:13, Rob Herring <robh@kernel.org> wrote:
>
> On Fri, Jan 20, 2023 at 4:04 PM Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Rob,
> >
> > On Thu, 19 Jan 2023 at 11:11, Rob Herring <robh@kernel.org> wrote:
> > >
> > > On Thu, Jan 19, 2023 at 10:41 AM Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Abdellatif,
> > > >
> > > > On Thu, 19 Jan 2023 at 09:32, Abdellatif El Khlifi
> > > > <abdellatif.elkhlifi@arm.com> wrote:
> > > > >
> > > > > On Wed, Jan 18, 2023 at 08:59:32AM -0500, Tom Rini wrote:
> > > > > > On Wed, Jan 18, 2023 at 01:46:54PM +0000, Sudeep Holla wrote:
> > > > > > > On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:
> > > > > > >
> > > > > > > >
> > > > > > > > I guess the problem comes down to, can we have one discovery method that
> > > > > > > > everyone shares, or do we have to let everyone invent a new discovery
> > > > > > > > method every time?
> > > > > > >
> > > > > > >
> > > > > > > No one needs to invent any discovery method every time if the firmware
> > > > > > > specification
> > > > > > > provides one and as Rob mentioned many times in the thread, all new firmware
> > > > > > > specification must provide one and we are trying to make sure that is
> > > > > > > the case with all new
> > > > > > > specs from Arm.
> > > > > > >
> > > > > > >
> > > > > > > > FF-A, Op-tee, U-Boot, coreboot, barebox (and
> > > > > > > > everyone else I'm unintentionally forgetting) could just discover these
> > > > > > > > things via device tree.
> > > > > > >
> > > > > > >
> > > > > > > I leave that to the individual projects to decide and agree but
> > > > > > > fundamentally if
> > > > > > > the specification provides a way to discover, not sure why we are even
> > > > > > > discussing
> > > > > > > an alternative method here.
> > > > > > >
> > > > > > >
> > > > > > > > Or, we could all write our own code to perform
> > > > > > > > the discovery.
> > > > > > >
> > > > > > >
> > > > > > > For what reason ? I can understand if there is no discovery mechanism but
> > > > > > > that's not the
> > > > > > > case in $subject.
> > > > > > >
> > > > > > >
> > > > > > > > And when RISC-V comes along with similar functionality,
> > > > > > > > we could probe their device tree and see they've implemented the same
> > > > > > > > concept, but a little differently, but still have the discovery portion
> > > > > > > > be in the device tree. To which it sounds like your answer is "not in
> > > > > > > > the device tree".
> > > > > > > >
> > > > > > >
> > > > > > > I see U-boot seem to have made a decision to create DT node for each and
> > > > > > > everything
> > > > > > > that needs to be added to DM which seems bit unfortunate but I don't
> > > > > > > understand the
> > > > > > > history/motive/background for it but I respect the decision if it is
> > > > > > > already made.
> > > > > > >
> > > > > > > These firmware interfaces are standard on all Arm platforms and can be
> > > > > > > discovered
> > > > > > > based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
> > > > > > > addition of DT nodes for all the f/w i/f on all the platforms that need the
> > > > > > > support when
> > > > > > > one can be just discovered.
> > > > > > >
> > > > > > > Sorry for the sudden appearance on this thread, I was avoiding getting into
> > > > > > > this but thought
> > > > > > > I will at least express my opinion and also the way the firmware
> > > > > > > specifications from Arm is
> > > > > > > expected to be evolved from now on. With that I will leave it to you and
> > > > > > > other U-boot
> > > > > > > maintainers and the community in general to decide the right course in this
> > > > > > > case.
> > > > > >
> > > > > > To be clear, if the position is that "this is what everyone else will
> > > > > > use, really" then yes, we'll follow this in U-Boot.
> > > > >
> > > > > Hi Simon, Tom,
> > > > >
> > > > > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > > > > undiscoverable base address.
> > > > >
> > > > > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > > > > interfaces. The FF-A spec [1] describes this in details.
> > > >
> > > > Can you add a DT node for the 'FF-A SW interfaces' and attach some
> > > > sort of top-level driver to that? Perhaps simple-bus, or your own
> > > > thing? You don't need to add compatible strings for subnodes (devices
> > > > that are discoverable within that).
> > >
> > > We already have that. It's just called 'arm,psci'. FF-A is not the
> > > top-level thing. SMCCC is. That's unfortunately called PSCI in DT
> > > because SMCCC grew out of PSCI. Evolution is ugly...
> > >
> > > It's like this:
> > >
> > > SMCCC
> > >   +--PSCI
> > >   +--TRNG
> > >   +--FF-A
> > >   +--SCMI (sometimes)
> > >   +--OP-TEE
> > >   +--...Whatever Arm comes up with next...
> >
> > OK well that sounds OK.
> >
> > So what is the problem here? We have an SMCCC top-level thing in the
> > DT and everything else can be bound from that, right? Are people on
> > this thread not aware of this...or am I still missing something?
> >
> > Can you point to the SMCCC driver in U-Boot? Is this
> > bind_smccc_features(), i.w.c. it looks like it does what I want...why
> > does this thread exist?
>
> I imagine the u-boot structure for all this has evolved like the
> bindings where each feature was developed independently. From my brief
> look at it, initialization of all the above features would need to be
> reworked to work as described.

OK, then perhaps this is making more sense to me now.

Abdellatif, can you please look at the above? We should have one
top-level node in the DT and have that driver bind the child devices.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-23 16:32                                                                                     ` Simon Glass
@ 2023-01-24 11:30                                                                                       ` Sudeep Holla
  2023-01-24 22:44                                                                                         ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Sudeep Holla @ 2023-01-24 11:30 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Sudeep Holla, Abdellatif El Khlifi, achin.gupta,
	xueliang.zhong, Drew.Reed, robh, jens.wiklander,
	ilias.apalodimas, u-boot

Hi Simon,

On Mon, Jan 23, 2023 at 09:32:19AM -0700, Simon Glass wrote:
> Hi Sudeep,
> 
> I'd like to see DT defined across firmware and OS, not just be a Linux
> thing.

Fair enough.

> It is a better approach than having little fiefdoms everywhere
> with their own config mechanisms.
>

Agreed.

> It seems that you have lots of build-time config in the ARM
> components.

Not really. I think I have not conveyed the setup details properly.
Let me try to explain with 2 hopefully simple examples:

1. Consider a system with a power controller running its own firmware and
   OS(or any other application software including U-Boot) interacting with
   it to get the required power resource access/modification.

   One such thing is CPU operating points(OPP). Typically on old systems,
   these are listing in the DT and OSPM drives them completely. Now on the
   newer systems like the one I am presenting, ideally we need to get the
   list of OPP from the f/w at runtime and use the information to drive it.

   Suppose we have these information statically built into DT, then if the
   firmware is upgraded and there is change in the OPP set or if the f/w
   detects some configuration(bios/similar) that requires change in the
   OPP set presented to the OSPM(or any other users), then the static info
   built in the DT is stale or wrong. And hence the use of DT in such a
   configuation or system is not correct unless DT is populated on the fly
   interacting with the firmware before DT is consumed by the users.

   This was one example which I was referring when I said I don't want to
   use the DT info over live firmware information.

2. Now the FF-A case, if the list of partitions on the system is listed in
   the DT and there is change in that list due to various reasons(firmware
   upgrade, reconfiguration, resource disabled for a specific reason,...etc)
   then the list will be stale when presented to the user(OSPM/Linux/U-Boot)
   if it is not updated on the fly before the DT data is consumed.

Since in both the cases the firmware provides interface to the users to get
the information at runtime, I am against using the DT as source of
information.

-- 
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-23 16:32                                                                                 ` Simon Glass
@ 2023-01-24 15:56                                                                                   ` Abdellatif El Khlifi
  2023-01-24 22:44                                                                                     ` Simon Glass
                                                                                                       ` (2 more replies)
  2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  1 sibling, 3 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-01-24 15:56 UTC (permalink / raw)
  To: Simon Glass, Rob Herring
  Cc: trini, achin.gupta, xueliang.zhong, Drew.Reed, sudeep.holla,
	jens.wiklander, ilias.apalodimas, nd, u-boot

On Mon, Jan 23, 2023 at 09:32:28AM -0700, Simon Glass wrote:
> Hi Rob,
> 
> On Mon, 23 Jan 2023 at 08:13, Rob Herring <robh@kernel.org> wrote:
> >
> > On Fri, Jan 20, 2023 at 4:04 PM Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Rob,
> > >
> > > On Thu, 19 Jan 2023 at 11:11, Rob Herring <robh@kernel.org> wrote:
> > > >
> > > > On Thu, Jan 19, 2023 at 10:41 AM Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > Hi Abdellatif,
> > > > >
> > > > > On Thu, 19 Jan 2023 at 09:32, Abdellatif El Khlifi
> > > > > <abdellatif.elkhlifi@arm.com> wrote:
> > > > > >
> > > > > > On Wed, Jan 18, 2023 at 08:59:32AM -0500, Tom Rini wrote:
> > > > > > > On Wed, Jan 18, 2023 at 01:46:54PM +0000, Sudeep Holla wrote:
> > > > > > > > On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:
> > > > > > > >
> > > > > > > > >
> > > > > > > > > I guess the problem comes down to, can we have one discovery method that
> > > > > > > > > everyone shares, or do we have to let everyone invent a new discovery
> > > > > > > > > method every time?
> > > > > > > >
> > > > > > > >
> > > > > > > > No one needs to invent any discovery method every time if the firmware
> > > > > > > > specification
> > > > > > > > provides one and as Rob mentioned many times in the thread, all new firmware
> > > > > > > > specification must provide one and we are trying to make sure that is
> > > > > > > > the case with all new
> > > > > > > > specs from Arm.
> > > > > > > >
> > > > > > > >
> > > > > > > > > FF-A, Op-tee, U-Boot, coreboot, barebox (and
> > > > > > > > > everyone else I'm unintentionally forgetting) could just discover these
> > > > > > > > > things via device tree.
> > > > > > > >
> > > > > > > >
> > > > > > > > I leave that to the individual projects to decide and agree but
> > > > > > > > fundamentally if
> > > > > > > > the specification provides a way to discover, not sure why we are even
> > > > > > > > discussing
> > > > > > > > an alternative method here.
> > > > > > > >
> > > > > > > >
> > > > > > > > > Or, we could all write our own code to perform
> > > > > > > > > the discovery.
> > > > > > > >
> > > > > > > >
> > > > > > > > For what reason ? I can understand if there is no discovery mechanism but
> > > > > > > > that's not the
> > > > > > > > case in $subject.
> > > > > > > >
> > > > > > > >
> > > > > > > > > And when RISC-V comes along with similar functionality,
> > > > > > > > > we could probe their device tree and see they've implemented the same
> > > > > > > > > concept, but a little differently, but still have the discovery portion
> > > > > > > > > be in the device tree. To which it sounds like your answer is "not in
> > > > > > > > > the device tree".
> > > > > > > > >
> > > > > > > >
> > > > > > > > I see U-boot seem to have made a decision to create DT node for each and
> > > > > > > > everything
> > > > > > > > that needs to be added to DM which seems bit unfortunate but I don't
> > > > > > > > understand the
> > > > > > > > history/motive/background for it but I respect the decision if it is
> > > > > > > > already made.
> > > > > > > >
> > > > > > > > These firmware interfaces are standard on all Arm platforms and can be
> > > > > > > > discovered
> > > > > > > > based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
> > > > > > > > addition of DT nodes for all the f/w i/f on all the platforms that need the
> > > > > > > > support when
> > > > > > > > one can be just discovered.
> > > > > > > >
> > > > > > > > Sorry for the sudden appearance on this thread, I was avoiding getting into
> > > > > > > > this but thought
> > > > > > > > I will at least express my opinion and also the way the firmware
> > > > > > > > specifications from Arm is
> > > > > > > > expected to be evolved from now on. With that I will leave it to you and
> > > > > > > > other U-boot
> > > > > > > > maintainers and the community in general to decide the right course in this
> > > > > > > > case.
> > > > > > >
> > > > > > > To be clear, if the position is that "this is what everyone else will
> > > > > > > use, really" then yes, we'll follow this in U-Boot.
> > > > > >
> > > > > > Hi Simon, Tom,
> > > > > >
> > > > > > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > > > > > undiscoverable base address.
> > > > > >
> > > > > > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > > > > > interfaces. The FF-A spec [1] describes this in details.
> > > > >
> > > > > Can you add a DT node for the 'FF-A SW interfaces' and attach some
> > > > > sort of top-level driver to that? Perhaps simple-bus, or your own
> > > > > thing? You don't need to add compatible strings for subnodes (devices
> > > > > that are discoverable within that).
> > > >
> > > > We already have that. It's just called 'arm,psci'. FF-A is not the
> > > > top-level thing. SMCCC is. That's unfortunately called PSCI in DT
> > > > because SMCCC grew out of PSCI. Evolution is ugly...
> > > >
> > > > It's like this:
> > > >
> > > > SMCCC
> > > >   +--PSCI
> > > >   +--TRNG
> > > >   +--FF-A
> > > >   +--SCMI (sometimes)
> > > >   +--OP-TEE
> > > >   +--...Whatever Arm comes up with next...
> > >
> > > OK well that sounds OK.
> > >
> > > So what is the problem here? We have an SMCCC top-level thing in the
> > > DT and everything else can be bound from that, right? Are people on
> > > this thread not aware of this...or am I still missing something?
> > >
> > > Can you point to the SMCCC driver in U-Boot? Is this
> > > bind_smccc_features(), i.w.c. it looks like it does what I want...why
> > > does this thread exist?
> >
> > I imagine the u-boot structure for all this has evolved like the
> > bindings where each feature was developed independently. From my brief
> > look at it, initialization of all the above features would need to be
> > reworked to work as described.
> 
> OK, then perhaps this is making more sense to me now.
> 
> Abdellatif, can you please look at the above? We should have one
> top-level node in the DT and have that driver bind the child devices.
> 
> Regards,
> Simon

Hi Simon, Rob,

I'd like to suggest the creation of a root node called arm_smccc as shown below.

This node is the parent of all nodes using SMC calls like FF-A, PSCI, optee, ...

The first child to be integrated in the arm_smccc root node is FF-A. Hopefully, in the future the other features such as PSCI could be integrated under arm_smccc as well.

Th root node looks like this:

	firmware {
			arm_smccc {
		
			compatible = "arm,smccc-1.2";
			
			arm_ffa {
				compatible = "arm,ffa";
				method          = "smc";
			};

			psci {
				compatible      = "arm,psci";
				method          = "smc";
			};

			optee {
				compatible = "linaro,optee-tz";
				method = "smc";
			};

		};
	};

What do you think guys ?

Kind regards,
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-24 15:56                                                                                   ` Abdellatif El Khlifi
@ 2023-01-24 22:44                                                                                     ` Simon Glass
  2023-01-25  7:48                                                                                     ` Sudeep Holla
  2023-01-25 16:00                                                                                     ` Rob Herring
  2 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-01-24 22:44 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Rob Herring, trini, achin.gupta, xueliang.zhong, Drew.Reed,
	sudeep.holla, jens.wiklander, ilias.apalodimas, nd, u-boot

Hi Abdellatif,

On Tue, 24 Jan 2023 at 08:56, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> On Mon, Jan 23, 2023 at 09:32:28AM -0700, Simon Glass wrote:
> > Hi Rob,
> >
> > On Mon, 23 Jan 2023 at 08:13, Rob Herring <robh@kernel.org> wrote:
> > >
> > > On Fri, Jan 20, 2023 at 4:04 PM Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Rob,
> > > >
> > > > On Thu, 19 Jan 2023 at 11:11, Rob Herring <robh@kernel.org> wrote:
> > > > >
> > > > > On Thu, Jan 19, 2023 at 10:41 AM Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > Hi Abdellatif,
> > > > > >
> > > > > > On Thu, 19 Jan 2023 at 09:32, Abdellatif El Khlifi
> > > > > > <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > >
> > > > > > > On Wed, Jan 18, 2023 at 08:59:32AM -0500, Tom Rini wrote:
> > > > > > > > On Wed, Jan 18, 2023 at 01:46:54PM +0000, Sudeep Holla wrote:
> > > > > > > > > On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:
> > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > I guess the problem comes down to, can we have one discovery method that
> > > > > > > > > > everyone shares, or do we have to let everyone invent a new discovery
> > > > > > > > > > method every time?
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > No one needs to invent any discovery method every time if the firmware
> > > > > > > > > specification
> > > > > > > > > provides one and as Rob mentioned many times in the thread, all new firmware
> > > > > > > > > specification must provide one and we are trying to make sure that is
> > > > > > > > > the case with all new
> > > > > > > > > specs from Arm.
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > FF-A, Op-tee, U-Boot, coreboot, barebox (and
> > > > > > > > > > everyone else I'm unintentionally forgetting) could just discover these
> > > > > > > > > > things via device tree.
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > I leave that to the individual projects to decide and agree but
> > > > > > > > > fundamentally if
> > > > > > > > > the specification provides a way to discover, not sure why we are even
> > > > > > > > > discussing
> > > > > > > > > an alternative method here.
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > Or, we could all write our own code to perform
> > > > > > > > > > the discovery.
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > For what reason ? I can understand if there is no discovery mechanism but
> > > > > > > > > that's not the
> > > > > > > > > case in $subject.
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > And when RISC-V comes along with similar functionality,
> > > > > > > > > > we could probe their device tree and see they've implemented the same
> > > > > > > > > > concept, but a little differently, but still have the discovery portion
> > > > > > > > > > be in the device tree. To which it sounds like your answer is "not in
> > > > > > > > > > the device tree".
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > > I see U-boot seem to have made a decision to create DT node for each and
> > > > > > > > > everything
> > > > > > > > > that needs to be added to DM which seems bit unfortunate but I don't
> > > > > > > > > understand the
> > > > > > > > > history/motive/background for it but I respect the decision if it is
> > > > > > > > > already made.
> > > > > > > > >
> > > > > > > > > These firmware interfaces are standard on all Arm platforms and can be
> > > > > > > > > discovered
> > > > > > > > > based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
> > > > > > > > > addition of DT nodes for all the f/w i/f on all the platforms that need the
> > > > > > > > > support when
> > > > > > > > > one can be just discovered.
> > > > > > > > >
> > > > > > > > > Sorry for the sudden appearance on this thread, I was avoiding getting into
> > > > > > > > > this but thought
> > > > > > > > > I will at least express my opinion and also the way the firmware
> > > > > > > > > specifications from Arm is
> > > > > > > > > expected to be evolved from now on. With that I will leave it to you and
> > > > > > > > > other U-boot
> > > > > > > > > maintainers and the community in general to decide the right course in this
> > > > > > > > > case.
> > > > > > > >
> > > > > > > > To be clear, if the position is that "this is what everyone else will
> > > > > > > > use, really" then yes, we'll follow this in U-Boot.
> > > > > > >
> > > > > > > Hi Simon, Tom,
> > > > > > >
> > > > > > > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > > > > > > undiscoverable base address.
> > > > > > >
> > > > > > > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > > > > > > interfaces. The FF-A spec [1] describes this in details.
> > > > > >
> > > > > > Can you add a DT node for the 'FF-A SW interfaces' and attach some
> > > > > > sort of top-level driver to that? Perhaps simple-bus, or your own
> > > > > > thing? You don't need to add compatible strings for subnodes (devices
> > > > > > that are discoverable within that).
> > > > >
> > > > > We already have that. It's just called 'arm,psci'. FF-A is not the
> > > > > top-level thing. SMCCC is. That's unfortunately called PSCI in DT
> > > > > because SMCCC grew out of PSCI. Evolution is ugly...
> > > > >
> > > > > It's like this:
> > > > >
> > > > > SMCCC
> > > > >   +--PSCI
> > > > >   +--TRNG
> > > > >   +--FF-A
> > > > >   +--SCMI (sometimes)
> > > > >   +--OP-TEE
> > > > >   +--...Whatever Arm comes up with next...
> > > >
> > > > OK well that sounds OK.
> > > >
> > > > So what is the problem here? We have an SMCCC top-level thing in the
> > > > DT and everything else can be bound from that, right? Are people on
> > > > this thread not aware of this...or am I still missing something?
> > > >
> > > > Can you point to the SMCCC driver in U-Boot? Is this
> > > > bind_smccc_features(), i.w.c. it looks like it does what I want...why
> > > > does this thread exist?
> > >
> > > I imagine the u-boot structure for all this has evolved like the
> > > bindings where each feature was developed independently. From my brief
> > > look at it, initialization of all the above features would need to be
> > > reworked to work as described.
> >
> > OK, then perhaps this is making more sense to me now.
> >
> > Abdellatif, can you please look at the above? We should have one
> > top-level node in the DT and have that driver bind the child devices.
> >
> > Regards,
> > Simon
>
> Hi Simon, Rob,
>
> I'd like to suggest the creation of a root node called arm_smccc as shown below.
>
> This node is the parent of all nodes using SMC calls like FF-A, PSCI, optee, ...
>
> The first child to be integrated in the arm_smccc root node is FF-A. Hopefully, in the future the other features such as PSCI could be integrated under arm_smccc as well.
>
> Th root node looks like this:
>
>         firmware {
>                         arm_smccc {
>
>                         compatible = "arm,smccc-1.2";
>
>                         arm_ffa {
>                                 compatible = "arm,ffa";
>                                 method          = "smc";
>                         };
>
>                         psci {
>                                 compatible      = "arm,psci";
>                                 method          = "smc";
>                         };
>
>                         optee {
>                                 compatible = "linaro,optee-tz";
>                                 method = "smc";
>                         };
>
>                 };
>         };
>
> What do you think guys ?

LGTM, thanks.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-24 11:30                                                                                       ` Sudeep Holla
@ 2023-01-24 22:44                                                                                         ` Simon Glass
  2023-01-25  7:39                                                                                           ` Sudeep Holla
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-01-24 22:44 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, xueliang.zhong,
	Drew.Reed, robh, jens.wiklander, ilias.apalodimas, u-boot

Hi Sudeep,

On Tue, 24 Jan 2023 at 04:30, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
> Hi Simon,
>
> On Mon, Jan 23, 2023 at 09:32:19AM -0700, Simon Glass wrote:
> > Hi Sudeep,
> >
> > I'd like to see DT defined across firmware and OS, not just be a Linux
> > thing.
>
> Fair enough.
>
> > It is a better approach than having little fiefdoms everywhere
> > with their own config mechanisms.
> >
>
> Agreed.
>
> > It seems that you have lots of build-time config in the ARM
> > components.
>
> Not really. I think I have not conveyed the setup details properly.
> Let me try to explain with 2 hopefully simple examples:
>
> 1. Consider a system with a power controller running its own firmware and
>    OS(or any other application software including U-Boot) interacting with
>    it to get the required power resource access/modification.
>
>    One such thing is CPU operating points(OPP). Typically on old systems,
>    these are listing in the DT and OSPM drives them completely. Now on the
>    newer systems like the one I am presenting, ideally we need to get the
>    list of OPP from the f/w at runtime and use the information to drive it.
>
>    Suppose we have these information statically built into DT, then if the
>    firmware is upgraded and there is change in the OPP set or if the f/w
>    detects some configuration(bios/similar) that requires change in the
>    OPP set presented to the OSPM(or any other users), then the static info
>    built in the DT is stale or wrong. And hence the use of DT in such a
>    configuation or system is not correct unless DT is populated on the fly
>    interacting with the firmware before DT is consumed by the users.
>
>    This was one example which I was referring when I said I don't want to
>    use the DT info over live firmware information.

So you need to rebuild the firmware component to update the
information? That's not nice.

These parameters need to be factored out of the code. The best way to
do that is to put them in the DT. The DT should configure all of
firmware. It should not be necessary to rebuild all the code to update
a few parameters in the build.

Also these parameters should not be 'buried' in the code. I'd really
like you to consider the difference between code and data, with the
(configurable) data being in DT.

>
> 2. Now the FF-A case, if the list of partitions on the system is listed in
>    the DT and there is change in that list due to various reasons(firmware
>    upgrade, reconfiguration, resource disabled for a specific reason,...etc)
>    then the list will be stale when presented to the user(OSPM/Linux/U-Boot)
>    if it is not updated on the fly before the DT data is consumed.

U-Boot can set this up in the DT if that is what you want, but I think
you are confusing two things:

- what is available to use (i.e. drivers or code that is compiled in)
- what we actually want to use and how each piece if configured (this
should be handled at runtime)

Imagine your code is a Linux kernel. We don't hard-code these sorts of
settings in Linux.

>
> Since in both the cases the firmware provides interface to the users to get
> the information at runtime, I am against using the DT as source of
> information.

Well we should figure out a time or place to talk about this, as I
believe this is heading down the wrong path. As firmware gets more
complex, we need a unified configuration mechanism and proper
visibility into each component and what it is doing. They need to act
as a unified whole, not as a collection of blobs that might conflict.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-24 22:44                                                                                         ` Simon Glass
@ 2023-01-25  7:39                                                                                           ` Sudeep Holla
  0 siblings, 0 replies; 478+ messages in thread
From: Sudeep Holla @ 2023-01-25  7:39 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Abdellatif El Khlifi, Sudeep Holla, achin.gupta,
	xueliang.zhong, Drew.Reed, robh, jens.wiklander,
	ilias.apalodimas, u-boot

On Tue, Jan 24, 2023 at 03:44:53PM -0700, Simon Glass wrote:
> Hi Sudeep,
> 
> On Tue, 24 Jan 2023 at 04:30, Sudeep Holla <sudeep.holla@arm.com> wrote:
> >
> > Hi Simon,
> >

[...]

> > Not really. I think I have not conveyed the setup details properly.
> > Let me try to explain with 2 hopefully simple examples:
> >
> > 1. Consider a system with a power controller running its own firmware and
> >    OS(or any other application software including U-Boot) interacting with
> >    it to get the required power resource access/modification.
> >
> >    One such thing is CPU operating points(OPP). Typically on old systems,
> >    these are listing in the DT and OSPM drives them completely. Now on the
> >    newer systems like the one I am presenting, ideally we need to get the
> >    list of OPP from the f/w at runtime and use the information to drive it.
> >
> >    Suppose we have these information statically built into DT, then if the
> >    firmware is upgraded and there is change in the OPP set or if the f/w
> >    detects some configuration(bios/similar) that requires change in the
> >    OPP set presented to the OSPM(or any other users), then the static info
> >    built in the DT is stale or wrong. And hence the use of DT in such a
> >    configuation or system is not correct unless DT is populated on the fly
> >    interacting with the firmware before DT is consumed by the users.
> >
> >    This was one example which I was referring when I said I don't want to
> >    use the DT info over live firmware information.
>
> So you need to rebuild the firmware component to update the
> information? That's not nice.
>

Well, I understand the firmware component itself can fetch these data from
the DT, but not all firmware are built with DT support to start with(for
simple reasons like they need to run with very limited ram in orders of few
kB).

Even if they did, they might have independent DT blob with the data
required for the firmware to function.

The holy grail of system DT is yet to see the reality IMO.

And this rebuild is very much needed during development and updating
DT for the data makes no sense to me when the Linux kernel can query the
same through standard interfaces defined by the firmware. There can be
no argument to no use the interface to fetch the data runtime as it will
be most accurate than any other data. DT may have more data or data that
firmware decided not to support runtime for various reasons(I think I
mentioned couple earlier). So, strict no to static data from the DT and
even if some boot code updates it, I trust getting it from the firmware
if and when possible. The interface has been added considering all these.
It is agnostic of firmware designs and implementation. Assuming DT support
in the firmware just makes these unnecessarily hard.

> These parameters need to be factored out of the code. The best way to
> do that is to put them in the DT. The DT should configure all of
> firmware. It should not be necessary to rebuild all the code to update
> a few parameters in the build.
>

Completely agreed in terms of design, but in reality not all implementations
want to follow that for reasons of their own.

> Also these parameters should not be 'buried' in the code. I'd really
> like you to consider the difference between code and data, with the
> (configurable) data being in DT.
>

Again agreed, but this is something we are enforcing in the Linux kernel
and U-Boot. It is not universal and IMO it may never be. The firmware
interfaces are defined to cope up with these and they are bound to stay.
DT can never replace it. Further like ACPI, these firmware interface
don't just provide static data, it also supports run-time. So there is
some advantage and are here to stay. Preferring DT data for sake of
uniformity and simplicity are not going to sway the wind away from these
interface to the DT. I am definitely not for it for all the reasons I have
already mentioned.

> >
> > 2. Now the FF-A case, if the list of partitions on the system is listed in
> >    the DT and there is change in that list due to various reasons(firmware
> >    upgrade, reconfiguration, resource disabled for a specific reason,...etc)
> >    then the list will be stale when presented to the user(OSPM/Linux/U-Boot)
> >    if it is not updated on the fly before the DT data is consumed.
>
> U-Boot can set this up in the DT if that is what you want, but I think
> you are confusing two things:
>
> - what is available to use (i.e. drivers or code that is compiled in)
> - what we actually want to use and how each piece if configured (this
> should be handled at runtime)
>

No I understand all these and advantages you have been mentioning. But
there is also other side of the story and that's what I have been trying
to group as firmware interface.

> Imagine your code is a Linux kernel. We don't hard-code these sorts of
> settings in Linux.
>

Yes definitely and I agree as mentioned quite a few times above. But that
doesn't change a bit as already mentioned.

> >
> > Since in both the cases the firmware provides interface to the users to get
> > the information at runtime, I am against using the DT as source of
> > information.
>
> Well we should figure out a time or place to talk about this, as I
> believe this is heading down the wrong path.

If you strongly believe that, then you need to speak with architects who
are designing and standardising these interfaces taking with the various
Arm silicon vendors/partners. I am also sure your employer is one of them
and have their means to get in touch with the right people.

> As firmware gets more complex,

Indeed, they are already getting complex and it is necessitating the
need for such interfaces as we are dealing with dynamic component as well
not just static to use DT as standard and unified mechanism.

> we need a unified configuration mechanism and proper visibility into
> each component and what it is doing. They need to act as a unified whole,
> not as a collection of blobs that might conflict.
>

Well that would be ideal and I would have agreed with that few years back
but not now as I have seen the evolution in the firmware space(that I am
involved and visible to me) and involved in the development of some of these
interface.

Main point based on these discussion is that you are looking at just the
static data needed and how DT can be used. The interfaces are also dealing
with the dynamic configurations and while at it they better deal with
static data as well instead of using alternatives like DT. I am not against
DT for the reasons you think it must be used, it is just that here it is
not sufficient.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-24 15:56                                                                                   ` Abdellatif El Khlifi
  2023-01-24 22:44                                                                                     ` Simon Glass
@ 2023-01-25  7:48                                                                                     ` Sudeep Holla
  2023-01-25 10:55                                                                                       ` Abdellatif El Khlifi
  2023-01-25 16:00                                                                                     ` Rob Herring
  2 siblings, 1 reply; 478+ messages in thread
From: Sudeep Holla @ 2023-01-25  7:48 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Simon Glass, Rob Herring, Sudeep Holla, trini, achin.gupta,
	xueliang.zhong, Drew.Reed, jens.wiklander, ilias.apalodimas, nd,
	u-boot

On Tue, Jan 24, 2023 at 03:56:19PM +0000, Abdellatif El Khlifi wrote:
>
> I'd like to suggest the creation of a root node called arm_smccc as shown below.
>

Not sure if U-Boot already supports the existing binding of PSCI and OPTEE.

> This node is the parent of all nodes using SMC calls like FF-A, PSCI, optee, ...
>

Well if you want to start with the clean slate for all new platforms, then
it is a good way. But you don't need any of the child nodes as they can all
be queried and discovered.

> The first child to be integrated in the arm_smccc root node is FF-A.
> Hopefully, in the future the other features such as PSCI could be integrated
> under arm_smccc as well.
>

You don't need FF-A or any other node if the presence of SMCCC node indicates
the support of SMCCC v1.1+(need to go back and check to confirm this).
You can query the presence of all the feature. There is no need to have a
node for each of the feature supported. That was the whole discussion of this
thread IIUC.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-25  7:48                                                                                     ` Sudeep Holla
@ 2023-01-25 10:55                                                                                       ` Abdellatif El Khlifi
  2023-01-25 12:54                                                                                         ` Sudeep Holla
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-01-25 10:55 UTC (permalink / raw)
  To: Sudeep Holla, Simon Glass, Rob Herring
  Cc: trini, achin.gupta, xueliang.zhong, Drew.Reed, jens.wiklander,
	ilias.apalodimas, nd, u-boot

On Wed, Jan 25, 2023 at 07:48:17AM +0000, Sudeep Holla wrote:
> On Tue, Jan 24, 2023 at 03:56:19PM +0000, Abdellatif El Khlifi wrote:
> >
> > I'd like to suggest the creation of a root node called arm_smccc as shown below.
> >
> 
> Not sure if U-Boot already supports the existing binding of PSCI and OPTEE.
> 
> > This node is the parent of all nodes using SMC calls like FF-A, PSCI, optee, ...
> >
> 
> Well if you want to start with the clean slate for all new platforms, then
> it is a good way. But you don't need any of the child nodes as they can all
> be queried and discovered.
> 
> > The first child to be integrated in the arm_smccc root node is FF-A.
> > Hopefully, in the future the other features such as PSCI could be integrated
> > under arm_smccc as well.
> >
> 
> You don't need FF-A or any other node if the presence of SMCCC node indicates
> the support of SMCCC v1.1+(need to go back and check to confirm this).
> You can query the presence of all the feature. There is no need to have a
> node for each of the feature supported. That was the whole discussion of this
> thread IIUC.
> 
> --
> Regards,
> Sudeep

Hi Simon, Rob, Sudeep

I'm tweaking my previous suggestion regarding the creation of a new arm_smccc root node.

This node is the parent of all SW features using SMC calls like FF-A, PSCI, optee, ...

However, no child node is created in the DT. The SW features are seen as architecture features
and can be discovered by querying through SMC calls.

So, when probed the arm_smccc device driver tries to discover the SW features (FF-A, PSCI, optee, ...)

by calling xxx_discover() API for each feature ( e.g: ffa_discover() ).

The xxx_discover() creates U-Boot device(s) for the feature and set arm_smccc as the parent.

"dm tree" command should show:

SMCCC
  +--PSCI
  +--TRNG
  +--FF-A
  +--SCMI (sometimes)
  +--OP-TEE
  +--...Whatever Arm comes up with next...

As Sudeep suggested, we only need this node:

firmware {
    arm_smccc {
        compatible = "arm,smccc-1.2";
    };
};

What do you think guys ? Are you happy with this approach ?

Kind regards,
Abdellatif


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-25 10:55                                                                                       ` Abdellatif El Khlifi
@ 2023-01-25 12:54                                                                                         ` Sudeep Holla
  0 siblings, 0 replies; 478+ messages in thread
From: Sudeep Holla @ 2023-01-25 12:54 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Simon Glass, Rob Herring, Sudeep Holla, trini, achin.gupta,
	xueliang.zhong, Drew.Reed, jens.wiklander, ilias.apalodimas, nd,
	u-boot

On Wed, Jan 25, 2023 at 10:55:11AM +0000, Abdellatif El Khlifi wrote:
> Hi Simon, Rob, Sudeep
>
> I'm tweaking my previous suggestion regarding the creation of a new
> arm_smccc root node..
>
> This node is the parent of all SW features using SMC calls like FF-A, PSCI,
> optee, ...
>
> However, no child node is created in the DT. The SW features are seen as
> architecture features and can be discovered by querying through SMC calls.
>
> So, when probed the arm_smccc device driver tries to discover the SW
> features (FF-A, PSCI, optee, ...) by calling xxx_discover() API for each
> feature ( e.g: ffa_discover() ).
>
> The xxx_discover() creates U-Boot device(s) for the feature and set
> arm_smccc as the parent.
>
> "dm tree" command should show:
>
> SMCCC
>   +--PSCI
>   +--TRNG
>   +--FF-A
>   +--SCMI (sometimes)
>   +--OP-TEE
>   +--...Whatever Arm comes up with next...
>
> As Sudeep suggested, we only need this node:
>
> firmware {
>     arm_smccc {
>         compatible = "arm,smccc-1.2";
>     };
> };
>
> What do you think guys ? Are you happy with this approach ?
>

This looks good to me. No objections binding per se.

However if you look at Rob's earlier comments, due to the way all these
firmware specs evolved and hence the corresponding binding, though PSCI
uses SMCCC like all other specs in the above list/tree, the PSCI binding
was introduced along with its implementation in the kernel. Also the
fact that until SMCCC v1.1, there was no version query feature in SMCCC
and PSCI_FEATURE was used instead. It is handled in the same way in the
kernel today.

Not sure if that is the reason Rob suggested just using PSCI node like
we do in the kernel today.

As I mentioned I am not against your suggestion as it would be the best
way to start if we were doing it today, but we have legacy to handle.
Let us see what is Rob's opinion. If we decide not to use PSCI like in
the kernel and add this new SMCCC, we may have to handle that in the kernel
and also preferably add checks in DTC to not have PSCI node if SMCCC is
present or something on that lines.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-24 15:56                                                                                   ` Abdellatif El Khlifi
  2023-01-24 22:44                                                                                     ` Simon Glass
  2023-01-25  7:48                                                                                     ` Sudeep Holla
@ 2023-01-25 16:00                                                                                     ` Rob Herring
  2023-01-25 16:44                                                                                       ` Abdellatif El Khlifi
  2 siblings, 1 reply; 478+ messages in thread
From: Rob Herring @ 2023-01-25 16:00 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Simon Glass, trini, achin.gupta, xueliang.zhong, Drew.Reed,
	sudeep.holla, jens.wiklander, ilias.apalodimas, nd, u-boot

On Tue, Jan 24, 2023 at 9:56 AM Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> On Mon, Jan 23, 2023 at 09:32:28AM -0700, Simon Glass wrote:
> > Hi Rob,
> >
> > On Mon, 23 Jan 2023 at 08:13, Rob Herring <robh@kernel.org> wrote:
> > >
> > > On Fri, Jan 20, 2023 at 4:04 PM Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Rob,
> > > >
> > > > On Thu, 19 Jan 2023 at 11:11, Rob Herring <robh@kernel.org> wrote:
> > > > >
> > > > > On Thu, Jan 19, 2023 at 10:41 AM Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > Hi Abdellatif,
> > > > > >
> > > > > > On Thu, 19 Jan 2023 at 09:32, Abdellatif El Khlifi
> > > > > > <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > >
> > > > > > > On Wed, Jan 18, 2023 at 08:59:32AM -0500, Tom Rini wrote:
> > > > > > > > On Wed, Jan 18, 2023 at 01:46:54PM +0000, Sudeep Holla wrote:
> > > > > > > > > On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:
> > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > I guess the problem comes down to, can we have one discovery method that
> > > > > > > > > > everyone shares, or do we have to let everyone invent a new discovery
> > > > > > > > > > method every time?
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > No one needs to invent any discovery method every time if the firmware
> > > > > > > > > specification
> > > > > > > > > provides one and as Rob mentioned many times in the thread, all new firmware
> > > > > > > > > specification must provide one and we are trying to make sure that is
> > > > > > > > > the case with all new
> > > > > > > > > specs from Arm.
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > FF-A, Op-tee, U-Boot, coreboot, barebox (and
> > > > > > > > > > everyone else I'm unintentionally forgetting) could just discover these
> > > > > > > > > > things via device tree.
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > I leave that to the individual projects to decide and agree but
> > > > > > > > > fundamentally if
> > > > > > > > > the specification provides a way to discover, not sure why we are even
> > > > > > > > > discussing
> > > > > > > > > an alternative method here.
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > Or, we could all write our own code to perform
> > > > > > > > > > the discovery.
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > For what reason ? I can understand if there is no discovery mechanism but
> > > > > > > > > that's not the
> > > > > > > > > case in $subject.
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > And when RISC-V comes along with similar functionality,
> > > > > > > > > > we could probe their device tree and see they've implemented the same
> > > > > > > > > > concept, but a little differently, but still have the discovery portion
> > > > > > > > > > be in the device tree. To which it sounds like your answer is "not in
> > > > > > > > > > the device tree".
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > > I see U-boot seem to have made a decision to create DT node for each and
> > > > > > > > > everything
> > > > > > > > > that needs to be added to DM which seems bit unfortunate but I don't
> > > > > > > > > understand the
> > > > > > > > > history/motive/background for it but I respect the decision if it is
> > > > > > > > > already made.
> > > > > > > > >
> > > > > > > > > These firmware interfaces are standard on all Arm platforms and can be
> > > > > > > > > discovered
> > > > > > > > > based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
> > > > > > > > > addition of DT nodes for all the f/w i/f on all the platforms that need the
> > > > > > > > > support when
> > > > > > > > > one can be just discovered.
> > > > > > > > >
> > > > > > > > > Sorry for the sudden appearance on this thread, I was avoiding getting into
> > > > > > > > > this but thought
> > > > > > > > > I will at least express my opinion and also the way the firmware
> > > > > > > > > specifications from Arm is
> > > > > > > > > expected to be evolved from now on. With that I will leave it to you and
> > > > > > > > > other U-boot
> > > > > > > > > maintainers and the community in general to decide the right course in this
> > > > > > > > > case.
> > > > > > > >
> > > > > > > > To be clear, if the position is that "this is what everyone else will
> > > > > > > > use, really" then yes, we'll follow this in U-Boot.
> > > > > > >
> > > > > > > Hi Simon, Tom,
> > > > > > >
> > > > > > > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > > > > > > undiscoverable base address.
> > > > > > >
> > > > > > > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > > > > > > interfaces. The FF-A spec [1] describes this in details.
> > > > > >
> > > > > > Can you add a DT node for the 'FF-A SW interfaces' and attach some
> > > > > > sort of top-level driver to that? Perhaps simple-bus, or your own
> > > > > > thing? You don't need to add compatible strings for subnodes (devices
> > > > > > that are discoverable within that).
> > > > >
> > > > > We already have that. It's just called 'arm,psci'. FF-A is not the
> > > > > top-level thing. SMCCC is. That's unfortunately called PSCI in DT
> > > > > because SMCCC grew out of PSCI. Evolution is ugly...
> > > > >
> > > > > It's like this:
> > > > >
> > > > > SMCCC
> > > > >   +--PSCI
> > > > >   +--TRNG
> > > > >   +--FF-A
> > > > >   +--SCMI (sometimes)
> > > > >   +--OP-TEE
> > > > >   +--...Whatever Arm comes up with next...
> > > >
> > > > OK well that sounds OK.
> > > >
> > > > So what is the problem here? We have an SMCCC top-level thing in the
> > > > DT and everything else can be bound from that, right? Are people on
> > > > this thread not aware of this...or am I still missing something?
> > > >
> > > > Can you point to the SMCCC driver in U-Boot? Is this
> > > > bind_smccc_features(), i.w.c. it looks like it does what I want...why
> > > > does this thread exist?
> > >
> > > I imagine the u-boot structure for all this has evolved like the
> > > bindings where each feature was developed independently. From my brief
> > > look at it, initialization of all the above features would need to be
> > > reworked to work as described.
> >
> > OK, then perhaps this is making more sense to me now.
> >
> > Abdellatif, can you please look at the above? We should have one
> > top-level node in the DT and have that driver bind the child devices.
> >
> > Regards,
> > Simon
>
> Hi Simon, Rob,
>
> I'd like to suggest the creation of a root node called arm_smccc as shown below.
>
> This node is the parent of all nodes using SMC calls like FF-A, PSCI, optee, ...
>
> The first child to be integrated in the arm_smccc root node is FF-A. Hopefully, in the future the other features such as PSCI could be integrated under arm_smccc as well.

So now instead of 1 binding being added, you are proposing 2 new
bindings ("arm,smccc-1.2" and "arm,ffa")?

Not only that, we'd have to support both the old way for all the
existing platforms and the new way.

> Th root node looks like this:
>
>         firmware {
>                         arm_smccc {
>
>                         compatible = "arm,smccc-1.2";

Stop here. That's all that needs to be in the DT. The rest is
discoverable. If we could redesign everything, then this is what we
would have. A node saying we have SMCCC. But we can't just redesign
everything. However, we already have such a node with the PSCI node
because PSCI implies SMCCC.

What u-boot needs is a driver for "arm,smccc-1.2" that then
instantiates FFA, PSCI, TRNG, etc. without DT. Except that it would
match on "arm,psci" instead of "arm,smccc-1.2".

Rob

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-25 16:00                                                                                     ` Rob Herring
@ 2023-01-25 16:44                                                                                       ` Abdellatif El Khlifi
  2023-01-25 17:11                                                                                         ` Sudeep Holla
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-01-25 16:44 UTC (permalink / raw)
  To: Rob Herring
  Cc: sjg, sudeep.holla, trini, achin.gupta, xueliang.zhong, Drew.Reed,
	jens.wiklander, ilias.apalodimas, nd, u-boot

On Wed, Jan 25, 2023 at 10:00:58AM -0600, Rob Herring wrote:
> On Tue, Jan 24, 2023 at 9:56 AM Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > On Mon, Jan 23, 2023 at 09:32:28AM -0700, Simon Glass wrote:
> > > Hi Rob,
> > >
> > > On Mon, 23 Jan 2023 at 08:13, Rob Herring <robh@kernel.org> wrote:
> > > >
> > > > On Fri, Jan 20, 2023 at 4:04 PM Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > Hi Rob,
> > > > >
> > > > > On Thu, 19 Jan 2023 at 11:11, Rob Herring <robh@kernel.org> wrote:
> > > > > >
> > > > > > On Thu, Jan 19, 2023 at 10:41 AM Simon Glass <sjg@chromium.org> wrote:
> > > > > > >
> > > > > > > Hi Abdellatif,
> > > > > > >
> > > > > > > On Thu, 19 Jan 2023 at 09:32, Abdellatif El Khlifi
> > > > > > > <abdellatif.elkhlifi@arm.com> wrote:
> > > > > > > >
> > > > > > > > On Wed, Jan 18, 2023 at 08:59:32AM -0500, Tom Rini wrote:
> > > > > > > > > On Wed, Jan 18, 2023 at 01:46:54PM +0000, Sudeep Holla wrote:
> > > > > > > > > > On Wed, Jan 18, 2023 at 12:49 PM Tom Rini <trini@konsulko.com> wrote:
> > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > I guess the problem comes down to, can we have one discovery method that
> > > > > > > > > > > everyone shares, or do we have to let everyone invent a new discovery
> > > > > > > > > > > method every time?
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > No one needs to invent any discovery method every time if the firmware
> > > > > > > > > > specification
> > > > > > > > > > provides one and as Rob mentioned many times in the thread, all new firmware
> > > > > > > > > > specification must provide one and we are trying to make sure that is
> > > > > > > > > > the case with all new
> > > > > > > > > > specs from Arm.
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > FF-A, Op-tee, U-Boot, coreboot, barebox (and
> > > > > > > > > > > everyone else I'm unintentionally forgetting) could just discover these
> > > > > > > > > > > things via device tree.
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > I leave that to the individual projects to decide and agree but
> > > > > > > > > > fundamentally if
> > > > > > > > > > the specification provides a way to discover, not sure why we are even
> > > > > > > > > > discussing
> > > > > > > > > > an alternative method here.
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > Or, we could all write our own code to perform
> > > > > > > > > > > the discovery.
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > For what reason ? I can understand if there is no discovery mechanism but
> > > > > > > > > > that's not the
> > > > > > > > > > case in $subject.
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > And when RISC-V comes along with similar functionality,
> > > > > > > > > > > we could probe their device tree and see they've implemented the same
> > > > > > > > > > > concept, but a little differently, but still have the discovery portion
> > > > > > > > > > > be in the device tree. To which it sounds like your answer is "not in
> > > > > > > > > > > the device tree".
> > > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > I see U-boot seem to have made a decision to create DT node for each and
> > > > > > > > > > everything
> > > > > > > > > > that needs to be added to DM which seems bit unfortunate but I don't
> > > > > > > > > > understand the
> > > > > > > > > > history/motive/background for it but I respect the decision if it is
> > > > > > > > > > already made.
> > > > > > > > > >
> > > > > > > > > > These firmware interfaces are standard on all Arm platforms and can be
> > > > > > > > > > discovered
> > > > > > > > > > based on PSCI/SMCCC. Not using the same and use DT node needs unnecessary
> > > > > > > > > > addition of DT nodes for all the f/w i/f on all the platforms that need the
> > > > > > > > > > support when
> > > > > > > > > > one can be just discovered.
> > > > > > > > > >
> > > > > > > > > > Sorry for the sudden appearance on this thread, I was avoiding getting into
> > > > > > > > > > this but thought
> > > > > > > > > > I will at least express my opinion and also the way the firmware
> > > > > > > > > > specifications from Arm is
> > > > > > > > > > expected to be evolved from now on. With that I will leave it to you and
> > > > > > > > > > other U-boot
> > > > > > > > > > maintainers and the community in general to decide the right course in this
> > > > > > > > > > case.
> > > > > > > > >
> > > > > > > > > To be clear, if the position is that "this is what everyone else will
> > > > > > > > > use, really" then yes, we'll follow this in U-Boot.
> > > > > > > >
> > > > > > > > Hi Simon, Tom,
> > > > > > > >
> > > > > > > > The FF-A transport is a SW bus and is not associated to any HW peripheral or
> > > > > > > > undiscoverable base address.
> > > > > > > >
> > > > > > > > There is only 1 way of discovering the FF-A bus and it's through the FF-A SW
> > > > > > > > interfaces. The FF-A spec [1] describes this in details.
> > > > > > >
> > > > > > > Can you add a DT node for the 'FF-A SW interfaces' and attach some
> > > > > > > sort of top-level driver to that? Perhaps simple-bus, or your own
> > > > > > > thing? You don't need to add compatible strings for subnodes (devices
> > > > > > > that are discoverable within that).
> > > > > >
> > > > > > We already have that. It's just called 'arm,psci'. FF-A is not the
> > > > > > top-level thing. SMCCC is. That's unfortunately called PSCI in DT
> > > > > > because SMCCC grew out of PSCI. Evolution is ugly...
> > > > > >
> > > > > > It's like this:
> > > > > >
> > > > > > SMCCC
> > > > > >   +--PSCI
> > > > > >   +--TRNG
> > > > > >   +--FF-A
> > > > > >   +--SCMI (sometimes)
> > > > > >   +--OP-TEE
> > > > > >   +--...Whatever Arm comes up with next...
> > > > >
> > > > > OK well that sounds OK.
> > > > >
> > > > > So what is the problem here? We have an SMCCC top-level thing in the
> > > > > DT and everything else can be bound from that, right? Are people on
> > > > > this thread not aware of this...or am I still missing something?
> > > > >
> > > > > Can you point to the SMCCC driver in U-Boot? Is this
> > > > > bind_smccc_features(), i.w.c. it looks like it does what I want...why
> > > > > does this thread exist?
> > > >
> > > > I imagine the u-boot structure for all this has evolved like the
> > > > bindings where each feature was developed independently. From my brief
> > > > look at it, initialization of all the above features would need to be
> > > > reworked to work as described.
> > >
> > > OK, then perhaps this is making more sense to me now.
> > >
> > > Abdellatif, can you please look at the above? We should have one
> > > top-level node in the DT and have that driver bind the child devices.
> > >
> > > Regards,
> > > Simon
> >
> > Hi Simon, Rob,
> >
> > I'd like to suggest the creation of a root node called arm_smccc as shown below.
> >
> > This node is the parent of all nodes using SMC calls like FF-A, PSCI, optee, ...
> >
> > The first child to be integrated in the arm_smccc root node is FF-A. Hopefully, in the future the other features such as PSCI could be integrated under arm_smccc as well.
> 
> So now instead of 1 binding being added, you are proposing 2 new
> bindings ("arm,smccc-1.2" and "arm,ffa")?
> 
> Not only that, we'd have to support both the old way for all the
> existing platforms and the new way.
> 
> > Th root node looks like this:
> >
> >         firmware {
> >                         arm_smccc {
> >
> >                         compatible = "arm,smccc-1.2";
> 
> Stop here. That's all that needs to be in the DT. The rest is
> discoverable. If we could redesign everything, then this is what we
> would have. A node saying we have SMCCC. But we can't just redesign
> everything. However, we already have such a node with the PSCI node
> because PSCI implies SMCCC.
> 
> What u-boot needs is a driver for "arm,smccc-1.2" that then
> instantiates FFA, PSCI, TRNG, etc. without DT. Except that it would
> match on "arm,psci" instead of "arm,smccc-1.2".
> 
> Rob

Thanks Rob. I already suggested something similar in a newer message, 
please have a look [1]. But the approach I'm suggesting is without using a PSCI node anymore.
Hopefully, the community would be interested in updating the older discovery designs
to use the one and only DT node: arm_smccc.

When probed the arm_smccc device driver tries to discover the SW features (FF-A, PSCI, optee, ...)
by calling xxx_discover() API for each feature.

firmware {
    arm_smccc {
        compatible = "arm,smccc-1.2";
    };
};

As a proof of concept, we can provide a first example with FF-A. Other SW
features (e.g: PSCI, optee, future ones, ...) can be added later on and
replace the older way of discovery.

Future SW features using SMC can be discovered by arm_smccc as well.
We can document this approach in U-Boot/Linux so future developments
will follow this approach.

[1]: https://lore.kernel.org/all/20230125105511.GA31193@e121910.cambridge.arm.com/

Kind regards,
Abdellatif


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-01-25 16:44                                                                                       ` Abdellatif El Khlifi
@ 2023-01-25 17:11                                                                                         ` Sudeep Holla
  0 siblings, 0 replies; 478+ messages in thread
From: Sudeep Holla @ 2023-01-25 17:11 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Rob Herring, sjg, trini, achin.gupta, xueliang.zhong, Drew.Reed,
	jens.wiklander, ilias.apalodimas, nd, u-boot

On Wed, Jan 25, 2023 at 04:44:34PM +0000, Abdellatif El Khlifi wrote:

[...]

> Future SW features using SMC can be discovered by arm_smccc as well.
> We can document this approach in U-Boot/Linux so future developments
> will follow this approach.
>

OK as discussed in private, you must not need any new binding. Also looking
(a very quick glance) at the U-Boot and in particular

"Commit 2fbe47b7e771 ("firmware: psci: bind arm smccc features when discovered")"

It looks like you have most of what you need already. Etienne has already
added mechanism for SMCCC discovery. You just need to extend things from
there if you need to support other features using SMCCC and discoverable
via SMCCC. Hope that helps.

-- 
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v9 00/10] introduce Arm FF-A support
  2023-01-23 16:32                                                                                 ` Simon Glass
  2023-01-24 15:56                                                                                   ` Abdellatif El Khlifi
@ 2023-03-10 14:10                                                                                   ` Abdellatif El Khlifi
  2023-03-10 14:10                                                                                     ` [PATCH v9 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                                                                       ` (10 more replies)
  1 sibling, 11 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-10 14:10 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong, Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].

FF-A describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World. These interfaces enable a pair of
software sandboxes to communicate with each other. A sandbox aka partition could
be a VM in the Normal or Secure world, an application in S-EL0, or a
Trusted OS in S-EL1.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

   => dm tree

    Class     Index  Probed  Driver                Name
   -----------------------------------------------------------
   ...
    firmware      0  [ + ]   psci                      |-- psci
    ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
   ...

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_get_device_by_name).

This implementation of the specification provides support for Aarch64.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

    - Discover the presence of secure partitions (SPs) of interest
    - Access an SP's service through communication protocols
      e.g. EFI MM communication protocol

The FF-A support provides the following features:

    - Being generic by design and can be used by any Arm 64-bit platform
    - The FF-A core driver
    - The driver provides driver operations to be used by clients to access the FF-A bus
    - FF-A driver can be compiled and used without EFI
    - Support for SMCCCv1.2 x0-x17 registers
    - Support for SMC32 calling convention
    - Support for 32-bit and 64-bit FF-A direct messaging
    - A new command called armffa is provided as an example of how to access the
      FF-A bus
    - An FF-A Sandbox driver is provided with test cases
    - Support for FF-A MM communication (compatible with EFI boot time)
    - Enabling FF-A and MM communication in Corstone1000 platform as a use case

For more details about the FF-A core driver please refer to [B] and refer to [C] for
how to use the armffa command.

Please find at [D] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of the major changes:
===========================

v9:

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
* align FF-A sandbox driver with FF-A discovery through DM
* use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
* add documentation for the armffa command: doc/usage/cmd/armffa.rst
* introduce testcase for uuid_str_to_le_bin

v8: [8]

* pass the FF-A bus device to the bus operations
* isolate the compilation choices between FF-A and OP-TEE
* drop OP-TEE configs from Corstone-1000 defconfig
* make ffa_get_partitions_info() second argument to be an SP count in both
  modes

v7: [7]

* add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v6: [6]

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

List of previous patches:

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
[7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
[8]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/

More details:

[A]: https://developer.arm.com/documentation/den0077/latest/
[B]: doc/arch/arm64.ffa.rst
[C]: doc/usage/cmd/armffa.rst
[D]: example of boot logs when enabling FF-A

```
   U-Boot 2023.01 (Mar 07 2023 - 11:05:21 +0000) corstone1000 aarch64

   DRAM:  2 GiB
   [FFA] trying FF-A framework discovery
   [FFA] Conduit is SMC
   [FFA] FF-A driver 1.0
   FF-A framework 1.0
   [FFA] Versions are compatible
   Core:  18 devices, 12 uclasses, devicetree: separate
   MMC:
   Loading Environment from nowhere... OK
   ...
   Hit any key to stop autoboot:  0
   Loading kernel from 0x083EE000 to memory ...
   ...
   [FFA] endpoint ID is 0
   [FFA] Using 1 4KB page(s) for RX/TX buffers size
   [FFA] RX buffer at virtual address 00000000fdf4e000
   [FFA] TX buffer at virtual address 00000000fdf50000
   [FFA] RX/TX buffers mapped
   [FFA] Reading partitions data from the RX buffer
   [FFA] Partition ID 8001 : info cached
   [FFA] Partition ID 8002 : info cached
   [FFA] Partition ID 8003 : info cached
   [FFA] 3 partition(s) found and cached
   [FFA] Preparing for checking partitions count
   [FFA] Searching partitions using the provided UUID
   [FFA] No partition found. Querying framework ...
   [FFA] Reading partitions data from the RX buffer
   [FFA] Number of partition(s) matching the UUID: 1
   EFI: Pre-allocating 1 partition(s) info structures
   [FFA] Preparing for filling partitions info
   [FFA] Searching partitions using the provided UUID
   [FFA] Partition ID 8003 matches the provided UUID
   EFI: MM partition ID 0x8003
   EFI: Corstone1000: Capsule shared buffer at 0x80000000 , size 8192 pages
   Booting /MemoryMapped(0x0,0x88200000,0xf00000)
   EFI stub: Booting Linux Kernel...
   EFI stub: Using DTB from configuration table
   EFI stub: Exiting boot services...
   [FFA] removing the device
   [FFA] unmapping RX/TX buffers
   [FFA] Freeing RX/TX buffers
   Booting Linux on physical CPU 0x0000000000 [0x411fd040]
   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
   Machine model: ARM Corstone1000 FPGA MPS3 board
   efi: EFI v2.100 by Das U-Boot
   ...
```

Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (10):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce uuid_str_to_le_bin function
  lib: uuid: introduce testcase for uuid_str_to_le_bin
  arm_ffa: introduce Arm FF-A low-level driver
  arm_ffa: introduce armffa command
  arm_ffa: introduce the FF-A Sandbox driver
  arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   17 +
 arch/arm/cpu/armv8/smccc-call.S               |   57 +-
 arch/arm/lib/asm-offsets.c                    |   16 +
 arch/sandbox/dts/sandbox.dtsi                 |    4 +
 arch/sandbox/dts/test.dts                     |    4 +
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    2 +
 cmd/armffa.c                                  |  264 ++++
 configs/corstone1000_defconfig                |    2 +
 configs/sandbox64_defconfig                   |    2 +
 configs/sandbox_defconfig                     |    2 +
 doc/arch/arm64.ffa.rst                        |  286 ++++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox/sandbox.rst                  |    1 +
 doc/usage/cmd/armffa.rst                      |  118 ++
 doc/usage/index.rst                           |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   39 +
 drivers/firmware/arm-ffa/Makefile             |    9 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     |   33 +
 drivers/firmware/arm-ffa/arm_ffa_priv.h       |  209 +++
 drivers/firmware/arm-ffa/core.c               | 1283 +++++++++++++++++
 drivers/firmware/arm-ffa/sandbox.c            |  610 ++++++++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |  129 ++
 include/arm_ffa.h                             |   89 ++
 include/configs/corstone1000.h                |   15 +-
 include/dm/uclass-id.h                        |    6 +
 include/linux/arm-smccc.h                     |   45 +
 include/mm_communication.h                    |    6 +
 include/sandbox_arm_ffa.h                     |  124 ++
 include/uuid.h                                |   15 +
 lib/efi_loader/Kconfig                        |   14 +-
 lib/efi_loader/efi_variable_tee.c             |  317 +++-
 lib/uuid.c                                    |   48 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   39 +
 test/dm/Makefile                              |    2 +
 test/dm/ffa.c                                 |  380 +++++
 test/lib/Makefile                             |    1 +
 test/lib/uuid.c                               |   44 +
 41 files changed, 4239 insertions(+), 9 deletions(-)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 doc/usage/cmd/armffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_priv.h
 create mode 100644 drivers/firmware/arm-ffa/core.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/sandbox_arm_ffa.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/lib/uuid.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v9 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-03-10 14:10                                                                                     ` Abdellatif El Khlifi
  2023-03-10 14:10                                                                                     ` [PATCH v9 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
                                                                                                       ` (9 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-10 14:10 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>

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

v9:

* update the copyright string

v7:

* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

 arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
 arch/arm/lib/asm-offsets.c      | 16 +++++++++
 include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..93f66d3366 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,7 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
- */
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+*/
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
 #include <generated/asm-offsets.h>
@@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 6de0ce9152..181a8ac4c2 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,11 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * 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>
@@ -90,6 +95,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#ifdef CONFIG_ARM64
+	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..f44e9e8f93 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +74,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v9 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2023-03-10 14:10                                                                                     ` [PATCH v9 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-03-10 14:10                                                                                     ` Abdellatif El Khlifi
  2023-03-10 20:49                                                                                       ` Simon Glass
  2023-03-10 14:10                                                                                     ` [PATCH v9 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
                                                                                                       ` (8 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-10 14:10 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

convert UUID string to little endian binary data

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>

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

v9:

* add a full function prototype description in uuid.h

v8:

* use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

 include/uuid.h | 15 +++++++++++++++
 lib/uuid.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..89b93e642b 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,10 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +48,15 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ * Return:
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 465e1ac38f..a72011e564 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * 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>
@@ -346,6 +350,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16;
+	u32 tmp32;
+	u64 tmp64;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+	memcpy(uuid_bin, &tmp32, 4);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16));
+	memcpy(uuid_bin + 10, &tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v9 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2023-03-10 14:10                                                                                     ` [PATCH v9 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2023-03-10 14:10                                                                                     ` [PATCH v9 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2023-03-10 14:10                                                                                     ` Abdellatif El Khlifi
  2023-03-10 14:10                                                                                     ` [PATCH v9 04/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
                                                                                                       ` (7 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-10 14:10 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

provide a test case

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Simon Glass <sjg@chromium.org>
---
 MAINTAINERS       |  5 +++++
 test/lib/Makefile |  1 +
 test/lib/uuid.c   | 44 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 50 insertions(+)
 create mode 100644 test/lib/uuid.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e29c16cf01..58370c5fbd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1596,3 +1596,8 @@ S:	Maintained
 F:	arch/arm/dts/ls1021a-twr-u-boot.dtsi
 F:	drivers/crypto/fsl/
 F:	include/fsl_sec.h
+
+UUID testing
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	test/lib/uuid.c
diff --git a/test/lib/Makefile b/test/lib/Makefile
index 7e7922fe3b..db6d88c065 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_UT_LIB_RSA) += rsa.o
 obj-$(CONFIG_AES) += test_aes.o
 obj-$(CONFIG_GETOPT) += getopt.o
 obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o
+obj-$(CONFIG_LIB_UUID) += uuid.o
 else
 obj-$(CONFIG_SANDBOX) += kconfig_spl.o
 endif
diff --git a/test/lib/uuid.c b/test/lib/uuid.c
new file mode 100644
index 0000000000..6f24939de4
--- /dev/null
+++ b/test/lib/uuid.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <uuid.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* test UUID */
+#define TEST_SVC_UUID	"ed32d533-4209-99e6-2d72-cdd998a79cc0"
+
+#define UUID_SIZE 16
+
+/* The UUID binary data (little-endian format) */
+static const u8 ref_uuid_bin[UUID_SIZE] = {
+	0x33, 0xd5, 0x32, 0xed,
+	0x09, 0x42, 0xe6, 0x99,
+	0x72, 0x2d, 0xc0, 0x9c,
+	0xa7, 0x98, 0xd9, 0xcd
+};
+
+static int lib_test_uuid_to_le(struct unit_test_state *uts)
+{
+	const char *uuid_str = TEST_SVC_UUID;
+	u8 ret_uuid_bin[UUID_SIZE] = {0};
+	int cnt;
+
+	ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin));
+
+	for (cnt = 0; cnt < UUID_SIZE; cnt++)
+		ut_asserteq(ref_uuid_bin[cnt], ret_uuid_bin[cnt]);
+
+	return 0;
+}
+
+LIB_TEST(lib_test_uuid_to_le, 0);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v9 04/10] arm_ffa: introduce Arm FF-A low-level driver
  2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                       ` (2 preceding siblings ...)
  2023-03-10 14:10                                                                                     ` [PATCH v9 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-03-10 14:10                                                                                     ` Abdellatif El Khlifi
  2023-03-10 14:10                                                                                     ` [PATCH v9 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                                                                       ` (6 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-10 14:10 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

Add the core driver implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_get_device_by_name).

The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- partition_info_get
- sync_send_receive
- rxtx_unmap

For more details please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

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>

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

v9:

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding

v8:

* make ffa_get_partitions_info() second argument to be an SP count in both
  modes
* update ffa_bus_prvdata_get() to return a pointer rather than a pointer
  address
* remove packing from ffa_partition_info and ffa_send_direct_data structures
* pass the FF-A bus device to the bus operations

v7:

* add support for 32-bit direct messaging
* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* improve the declaration of error handling mapping
* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the U-Boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the U-Boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

 MAINTAINERS                               |    7 +
 doc/arch/arm64.ffa.rst                    |  282 +++++
 doc/arch/index.rst                        |    1 +
 drivers/Makefile                          |    1 +
 drivers/firmware/Kconfig                  |    1 +
 drivers/firmware/arm-ffa/Kconfig          |   33 +
 drivers/firmware/arm-ffa/Makefile         |    8 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c |   33 +
 drivers/firmware/arm-ffa/arm_ffa_priv.h   |  209 ++++
 drivers/firmware/arm-ffa/core.c           | 1249 +++++++++++++++++++++
 include/arm_ffa.h                         |   88 ++
 include/dm/uclass-id.h                    |    6 +
 12 files changed, 1918 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm_ffa_priv.h
 create mode 100644 drivers/firmware/arm-ffa/core.c
 create mode 100644 include/arm_ffa.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 58370c5fbd..1dfa23c1f0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,6 +266,13 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	doc/arch/arm64.ffa.rst
+F:	drivers/firmware/arm-ffa/
+F:	include/arm_ffa.h
+
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..8fad9ef3d0
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,282 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Driver
+===============
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software sandboxes to
+communicate with each other. A sandbox aka partition could
+be a VM in the Normal or Secure world, an application in S-EL0, or a
+Trusted OS in S-EL1.
+
+This FF-A driver implements the interfaces to communicate with partitions in
+the Secure world aka Secure partitions (SPs).
+
+The driver specifically focuses on communicating with SPs that isolate portions
+of EFI runtime services that must run in a protected environment which is
+inaccessible by the Host OS or Hypervisor. Examples of such services are
+set/get variables.
+
+FF-A driver uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+At this stage of development the FF-A driver supports EFI boot time only.
+
+Runtime support will be added in future developments.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the driver relies on FF-A specification v1.0
+and uses SMC32 calling convention which means using the first 32-bit data of the
+Xn registers.
+
+At this stage we only need the FF-A v1.0 features.
+
+The driver has been tested with OP-TEE which supports SMC32 calling convention.
+
+For more details please refer to the FF-A v1.0 spec:
+https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification.
+
+For more details please refer to the SMC Calling Convention v1.2 spec:
+https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+CONFIG_ARM_FFA_TRANSPORT
+    Enables the FF-A bus driver. Turn this on if you want to use FF-A
+    communication.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+The ABI arguments are stored in x0 to x7 registers. Then, an SMC instruction
+is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-Boot FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs in the driver.
+
+FF-A bus discovery in U-Boot
+-------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
+an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
+This discovery mechanism is performed by the PSCI driver.
+
+The PSCI driver comes with a PSCI device tree node which is the root node for all
+architecture features including FF-A bus.
+
+::
+
+   => dm tree
+
+    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.
+
+In case of FF-A, the callback is ffa_bus_is_supported() which tries to discover the
+FF-A framework by querying the FF-A framework version from secure world using
+FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
+mechanism creates a U-Boot device for the FF-A bus and binds the FF-A driver
+with the device using device_bind_driver().
+
+At this stage the FF-A bus is registered with the DM and can be interacted with using
+the DM APIs.
+
+Clients are able to probe then use the FF-A bus by calling the DM class searching APIs
+(e.g: uclass_get_device_by_name). Please refer to the armffa command implementation
+as an example of how to probe and interact with the FF-A driver.
+
+When calling uclass_get_device_by_name() for example, the FF-A driver is probed
+and ffa_probe() is called which performs the following:
+
+    - allocating private data (priv) with devres
+    - updating priv with discovery information
+    - querying from secure world the u-boot endpoint ID
+    - querying from secure world the supported features of FFA_RXTX_MAP
+    - mapping the RX/TX buffers
+    - querying from secure world all the partitions information
+
+When one of the above actions fails, probing fails and the driver stays not active
+and can be probed again if needed.
+
+FF-A device destruction
+-------------------------
+
+When the FF-A device is removed by the DM, RX/TX buffers are automatically
+unmapped and freed. Same happens when the device is unbound before being
+removed first.
+
+For example, at EFI efi_exit_boot_services() active devices are automatically removed
+by dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL).
+
+By consequence, the FF-A RX/TX are unmapped automatically.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must query the SPs they are looking for
+during EFI boot time mode using the service UUID.
+
+The RX/TX buffers are only available at EFI boot time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped before EFI runtime mode starts.
+The driver provides a bus operation for that called rxtx_unmap() and this is done
+automatically at efi_exit_boot_services().
+
+If  RX/TX buffers created by U-Boot are not unmapped and by consequence becoming
+available at EFI runtime, secure world will get confused about RX/TX buffers
+ownership (U-Boot vs kernel).
+
+When invoking FF-A direct messaging, clients should specify which ABI protocol
+they want to use (32-bit vs 64-bit). Selecting the protocol means using
+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
+The calling convention between U-Boot and the secure world stays the same: SMC32.
+
+The bus driver layer
+------------------------------
+
+The driver comes on top of the SMCCC layer and is implemented in
+drivers/firmware/arm-ffa/core.c
+
+The driver provides the following features:
+
+- Support for the 32-bit version of the following ABIs:
+
+    - FFA_VERSION
+    - FFA_ID_GET
+    - FFA_FEATURES
+    - FFA_PARTITION_INFO_GET
+    - FFA_RXTX_UNMAP
+    - FFA_RX_RELEASE
+    - FFA_RUN
+    - FFA_ERROR
+    - FFA_SUCCESS
+    - FFA_INTERRUPT
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Support for the 64-bit version of the following ABIs:
+
+    - FFA_RXTX_MAP
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, the driver takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- The driver provides callbacks to be used by clients to access the FF-A bus:
+
+    - partition_info_get
+    - sync_send_receive
+    - rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+The armffa command
+-----------------------------------
+
+armffa is an implementation defined command showcasing how to use the FF-A driver and how to invoke
+its operations.
+
+Please refer the command documentation at doc/usage/cmd/armffa.rst
+
+Example of boot logs with FF-A enabled
+--------------------------------------
+
+For example, when using FF-A with Corstone-1000 the logs are as follows:
+
+::
+
+   U-Boot 2023.01 (Mar 07 2023 - 11:05:21 +0000) corstone1000 aarch64
+
+   DRAM:  2 GiB
+   [FFA] trying FF-A framework discovery
+   [FFA] Conduit is SMC
+   [FFA] FF-A driver 1.0
+   FF-A framework 1.0
+   [FFA] Versions are compatible
+   Core:  18 devices, 12 uclasses, devicetree: separate
+   MMC:
+   Loading Environment from nowhere... OK
+   ...
+   Hit any key to stop autoboot:  0
+   Loading kernel from 0x083EE000 to memory ...
+   ...
+   [FFA] endpoint ID is 0
+   [FFA] Using 1 4KB page(s) for RX/TX buffers size
+   [FFA] RX buffer at virtual address 00000000fdf4e000
+   [FFA] TX buffer at virtual address 00000000fdf50000
+   [FFA] RX/TX buffers mapped
+   [FFA] Reading partitions data from the RX buffer
+   [FFA] Partition ID 8001 : info cached
+   [FFA] Partition ID 8002 : info cached
+   [FFA] Partition ID 8003 : info cached
+   [FFA] 3 partition(s) found and cached
+   [FFA] Preparing for checking partitions count
+   [FFA] Searching partitions using the provided UUID
+   [FFA] No partition found. Querying framework ...
+   [FFA] Reading partitions data from the RX buffer
+   [FFA] Number of partition(s) matching the UUID: 1
+   EFI: Pre-allocating 1 partition(s) info structures
+   [FFA] Preparing for filling partitions info
+   [FFA] Searching partitions using the provided UUID
+   [FFA] Partition ID 8003 matches the provided UUID
+   EFI: MM partition ID 0x8003
+   EFI: Corstone1000: Capsule shared buffer at 0x80000000 , size 8192 pages
+   Booting /MemoryMapped(0x0,0x88200000,0xf00000)
+   EFI stub: Booting Linux Kernel...
+   EFI stub: Using DTB from configuration table
+   EFI stub: Exiting boot services...
+   [FFA] removing the device
+   [FFA] unmapping RX/TX buffers
+   [FFA] Freeing RX/TX buffers
+   Booting Linux on physical CPU 0x0000000000 [0x411fd040]
+   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
+   Machine model: ARM Corstone1000 FPGA MPS3 board
+   efi: EFI v2.100 by Das U-Boot
+   ...
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index b8da4b8c8e..2f916f4026 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Makefile b/drivers/Makefile
index 58be410135..885fdef4dc 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -112,6 +112,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index eae1c8ddc9..8789b1ea14 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
 	  the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
 	  services if any and reported as supported by the SMCCC firmware.
 
+source "drivers/firmware/arm-ffa/Kconfig"
 source "drivers/firmware/scmi/Kconfig"
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..e5b2912201
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select ARM_SMCCC_FEATURES
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  This driver is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
+	  FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
+	  by the PSCI driver.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  This FF-A driver takes care of all the interactions between Normal world
+	  and Secure World.
+
+	  For more details about the FF-A driver, please refer to doc/arch/arm64.ffa.rst
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..c8d83b4bc9
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,8 @@
+# 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>
+
+obj-y += arm-ffa-uclass.o core.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..bc4fe68d57
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,33 @@
+// 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 <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * ffa_bus_get_ops() - bus driver operations getter
+ * @dev:	the arm_ffa device
+ * Returns a pointer to the FF-A driver ops field.
+ * Return:
+ * The ops pointer on success, NULL on failure.
+ */
+const struct ffa_bus_ops *ffa_bus_get_ops(struct udevice *dev)
+{
+	if (!dev)
+		return NULL;
+
+	return device_get_ops(dev);
+}
+
+UCLASS_DRIVER(ffa) = {
+	.name		= "ffa",
+	.id		= UCLASS_FFA,
+};
diff --git a/drivers/firmware/arm-ffa/arm_ffa_priv.h b/drivers/firmware/arm-ffa/arm_ffa_priv.h
new file mode 100644
index 0000000000..51df7d1c64
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm_ffa_priv.h
@@ -0,0 +1,209 @@
+/* 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 __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <arm_ffa.h>
+#include <mapmem.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+
+/* This header is exclusively used by the FF-A core driver, sandbox driver and sandbox tests */
+
+/* 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
+/* CONFIG_ARM64 */
+#include <linux/arm-smccc.h>
+typedef struct arm_smccc_1_2_regs ffa_value_t;
+#endif
+
+/* Defining the function pointer type for the function executing the FF-A ABIs */
+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)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR                 = 0x60,
+	FFA_SUCCESS               = 0x61,
+	FFA_INTERRUPT             = 0x62,
+	FFA_VERSION               = 0x63,
+	FFA_FEATURES              = 0x64,
+	FFA_RX_RELEASE            = 0x65,
+	FFA_RXTX_MAP              = 0x66,
+	FFA_RXTX_UNMAP            = 0x67,
+	FFA_PARTITION_INFO_GET    = 0x68,
+	FFA_ID_GET                = 0x69,
+	FFA_RUN                   = 0x6d,
+	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
+	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
+
+	/* To be updated when adding new FFA IDs */
+	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
+	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
+};
+
+enum ffa_abi_errcode {
+	NOT_SUPPORTED = 1,
+	INVALID_PARAMETERS,
+	NO_MEMORY,
+	BUSY,
+	INTERRUPTED,
+	DENIED,
+	RETRY,
+	ABORTED,
+	MAX_NUMBER_FFA_ERR
+};
+
+/* Container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
+
+/*
+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
+ * @a1-4:	32-bit words access to the UUID data
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Hosts the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	void *rxbuf; /* Virtual address returned by memalign */
+	void *txbuf; /* Virtual address returned by memalign */
+	size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * Contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* Virtual address */
+};
+
+/**
+ * struct ffa_discovery_info - discovery information
+ * @fwk_version:	FF-A framework version
+ * @invoke_ffa_fn:	The function executing the FF-A function (ABI)
+ */
+struct ffa_discovery_info {
+	u32 fwk_version;
+	invoke_ffa_fn_t invoke_ffa_fn;
+};
+
+/**
+ * struct ffa_priv - the driver private data structure
+ *
+ * @dscvry_info:	Initial information discovered
+ * @ops:	The driver operations structure
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ *
+ * The device private data structure containing all the
+ * data read from secure world.
+ * The data is dynamically allocated, managed by devres
+ * and registered with the DM.
+ */
+struct ffa_priv {
+	struct ffa_discovery_info dscvry_info;
+	struct ffa_bus_ops ops;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+};
+#endif
diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
new file mode 100644
index 0000000000..2210f5343c
--- /dev/null
+++ b/drivers/firmware/arm-ffa/core.c
@@ -0,0 +1,1249 @@
+// 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 <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+#include "arm_ffa_priv.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* FF-A discovery information */
+struct ffa_discovery_info dscvry_info;
+
+/* The function that sets the SMC conduit */
+static int ffa_set_smc_conduit(void);
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	[NOT_SUPPORTED] = -EOPNOTSUPP,
+	[INVALID_PARAMETERS] = -EINVAL,
+	[NO_MEMORY] = -ENOMEM,
+	[BUSY] = -EBUSY,
+	[INTERRUPTED] = -EINTR,
+	[DENIED] = -EACCES,
+	[RETRY] = -EAGAIN,
+	[ABORTED] = -ECANCELED,
+};
+
+struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			[NO_MEMORY] =
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			[BUSY] =
+			"BUSY: RX buffer of the caller is not free",
+			[DENIED] =
+			"DENIED: Callee is not in a state to handle this request",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			[DENIED] =
+			"DENIED: Caller did not have ownership of the RX buffer",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			[NO_MEMORY] =
+			"NO_MEMORY: Not enough memory",
+			[DENIED] =
+			"DENIED: Buffer pair already registered",
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno() - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This function maps the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* Map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This function maps the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* Map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	log_err("[FFA] %s\n", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/* Driver core functions */
+
+/**
+ * ffa_get_version() - FFA_VERSION handler function
+ *
+ * This function implements FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_version(void)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	if (!dscvry_info.invoke_ffa_fn)
+		return -EINVAL;
+
+	dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	log_info("[FFA] FF-A driver %d.%d\nFF-A framework %d.%d\n",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) {
+		log_info("[FFA] Versions are compatible\n");
+
+		dscvry_info.fwk_version = res.a0;
+
+		return 0;
+	}
+
+	log_err("[FFA] versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id() - FFA_ID_GET handler function
+ * @dev: The FF-A bus device
+ *
+ * This function implements FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		log_info("[FFA] endpoint ID is %u\n", priv->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt() - sets the minimum number of pages in each of the RX/TX buffers
+ * @dev: The FF-A bus device
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * This function sets the minimum number of pages
+ *  in each of the RX/TX buffers in the private data structure
+ *
+ * Return:
+ *
+ * buf_4k_pages points to the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field)
+{
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	switch (prop_field) {
+	case RXTX_4K:
+		priv->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		priv->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		priv->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		log_err("[FFA] RX/TX buffer size not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features() - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ * @dev: The FF-A bus device
+ *
+ * This function implements FFA_FEATURES FF-A function
+ * to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers() - frees the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * This  function  frees the RX/TX buffers
+ */
+static void ffa_free_rxtx_buffers(struct udevice *dev)
+{
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	log_info("[FFA] Freeing RX/TX buffers\n");
+
+	if (priv->pair.rxbuf) {
+		free(priv->pair.rxbuf);
+		priv->pair.rxbuf = NULL;
+	}
+
+	if (priv->pair.txbuf) {
+		free(priv->pair.txbuf);
+		priv->pair.txbuf = NULL;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers() - allocates the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * This function is used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(struct udevice *dev)
+{
+	u64 bytes;
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	log_info("[FFA] Using %lu 4KB page(s) for RX/TX buffers size\n",
+		 priv->pair.rxtx_min_pages);
+
+	bytes = priv->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 * Assumption: Memory allocated with memalign is always physically contiguous
+	 */
+
+	priv->pair.rxbuf = memalign(bytes, bytes);
+	if (!priv->pair.rxbuf) {
+		log_err("[FFA] failure to allocate RX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_info("[FFA] RX buffer at virtual address %p\n", priv->pair.rxbuf);
+
+	priv->pair.txbuf = memalign(bytes, bytes);
+	if (!priv->pair.txbuf) {
+		free(priv->pair.rxbuf);
+		priv->pair.rxbuf = NULL;
+		log_err("[FFA] failure to allocate the TX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_info("[FFA] TX buffer at virtual address %p\n", priv->pair.txbuf);
+
+	/* Make sure the buffers are cleared before use */
+	memset(priv->pair.rxbuf, 0, bytes);
+	memset(priv->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers() - FFA_RXTX_MAP handler function
+ * @dev: The FF-A bus device
+ *
+ * This function implements FFA_RXTX_MAP FF-A function
+ * to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers(struct udevice *dev)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	ret = ffa_alloc_rxtx_buffers(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 * no need to convert from virtual to physical
+	 */
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = map_to_sysmem(priv->pair.txbuf),
+			.a2 = map_to_sysmem(priv->pair.rxbuf),
+			.a3 = priv->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		log_info("[FFA] RX/TX buffers mapped\n");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers(dev);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers() - FFA_RXTX_UNMAP handler function
+ * @dev: The arm_ffa bus device
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_unmap_rxtx_buffers(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *priv = NULL;
+
+	if (!dev)
+		return -ENODEV;
+
+	log_info("[FFA] unmapping RX/TX buffers\n");
+
+	priv = dev_get_priv(dev);
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(priv->id),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers(dev);
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer() - FFA_RX_RELEASE handler function
+ * @dev: The FF-A bus device
+ *
+ * This function invokes FFA_RX_RELEASE FF-A function
+ * to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical() - checks whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * This function is used by ffa_read_partitions_info to search
+ * for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+			    const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info() - reads queried partition data
+ * @dev: The arm_ffa bus device
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * This function reads the partitions information
+ * returned by the FFA_PARTITION_INFO_GET and saves it in the private
+ * data structure.
+ *
+ * Return:
+ *
+ * The private data structure is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(struct udevice *dev, u32 count,
+				    struct ffa_partition_uuid *part_uuid)
+{
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	if (!count) {
+		log_err("[FFA] no partition detected\n");
+		return -ENODATA;
+	}
+
+	log_info("[FFA] Reading partitions data from the RX buffer\n");
+
+	if (!part_uuid) {
+		/* Querying information of all partitions */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = priv->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			log_err("[FFA] partitions data size exceeds the RX buffer size:\n");
+			log_err("[FFA]     sizes in bytes: data %llu , RX buffer %llu\n",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO);
+		if (!priv->partitions.descs) {
+			log_err("[FFA] cannot  allocate partitions data buffer\n");
+			return -ENOMEM;
+		}
+
+		parts_info = priv->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			priv->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			log_info("[FFA] Partition ID %x : info cached\n",
+				 priv->partitions.descs[desc_idx].info.id);
+		}
+
+		priv->partitions.count = count;
+
+		log_info("[FFA] %d partition(s) found and cached\n", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = priv->pair.rxbuf;
+
+		/*
+		 * Search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/* Search the current ID in the cached partitions */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < priv->partitions.count;
+			     cached_desc_idx++) {
+				/* Save the UUID */
+				if (priv->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					priv->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info() - invokes FFA_PARTITION_INFO_GET and saves partitions data
+ * @dev: The arm_ffa bus device
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * This function executes the FFA_PARTITION_INFO_GET
+ * to query the partitions data. Then, it calls ffa_read_partitions_info
+ * to save the data in the private data structure.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid);
+			if (ret) {
+				log_err("[FFA] failed reading SP(s) data , err (%d)\n", ret);
+				ffa_release_rx_buffer(dev);
+				return -EINVAL;
+			}
+		}
+
+		/* Return the SP count (when querying using a UUID) */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer(dev);
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info() - FFA_PARTITION_INFO_GET handler function
+ *
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of partitions
+ *			 The variable will be set by the driver
+ *	@buffer: NULL
+ *
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@dev: The arm_ffa bus device
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of empty partition descriptors
+ *			 The variable will be read by the driver
+ *	@buffer: pointer to SPs information buffer
+ *		(allocated by the client and contains empty @sp_count descriptors).
+ *		The buffer will be filled by the driver
+ *
+ * This function queries the secure partition data from
+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * When invoked through a client request, ffa_get_partitions_info should be
+ * called twice. First call is to get from the driver the number of secure
+ * partitions (SPs) associated to a particular UUID.
+ * Then, the caller (client) allocates the buffer to host the SPs data and
+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
+ * buffer.
+ *
+ * To achieve the mechanism described above, ffa_get_partitions_info uses the
+ * following functions:
+ *		ffa_read_partitions_info
+ *		ffa_query_partitions_info
+ *
+ * Return:
+ *
+ * @sp_count: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer size, the buffer will be
+ * filled by the driver.
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+static int ffa_get_partitions_info(struct udevice *dev, const char *uuid_str,
+				   u32 *sp_count, struct ffa_partition_info *buffer)
+{
+	/*
+	 * fill_data:
+	 * 0: return the SP count
+	 * 1: fill SP data and return it to the caller
+	 */
+	bool fill_data = 0;
+	u32 desc_idx, client_desc_idx;
+	struct ffa_partition_uuid part_uuid = {0};
+	u32 sp_found = 0;
+	struct ffa_priv *priv = NULL;
+
+	if (!dev)
+		return -ENODEV;
+
+	priv = dev_get_priv(dev);
+
+	if (!priv->partitions.count || !priv->partitions.descs) {
+		log_err("[FFA] no partition installed\n");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		log_err("[FFA] no UUID provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_count) {
+		log_err("[FFA] no size/count provided\n");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		log_err("[FFA] invalid UUID\n");
+		return -EINVAL;
+	}
+
+	if (!buffer) {
+		/* Mode 1: getting the number of secure partitions */
+
+		fill_data = 0;
+
+		log_info("[FFA] Preparing for checking partitions count\n");
+
+	} else if (*sp_count) {
+		/* Mode 2: retrieving the partitions information */
+
+		fill_data = 1;
+
+		client_desc_idx = 0;
+
+		log_info("[FFA] Preparing for filling partitions info\n");
+
+	} else {
+		log_err("[FFA] invalid function arguments provided\n");
+		return -EINVAL;
+	}
+
+	log_info("[FFA] Searching partitions using the provided UUID\n");
+
+	/* Search in the cached partitions */
+	for (desc_idx = 0;
+	     desc_idx < priv->partitions.count;
+	     desc_idx++) {
+		if (ffa_uuid_are_identical(&priv->partitions.descs[desc_idx].sp_uuid,
+					   &part_uuid)) {
+			log_info("[FFA] Partition ID %x matches the provided UUID\n",
+				 priv->partitions.descs[desc_idx].info.id);
+
+			sp_found++;
+
+			if (fill_data) {
+				/* Trying to fill the partition info in the input buffer */
+
+				if (client_desc_idx < *sp_count) {
+					buffer[client_desc_idx++] =
+						priv->partitions.descs[desc_idx].info;
+					continue;
+				}
+
+				log_err("[FFA] failed to fill client descriptor, buffer full\n");
+				return -ENOBUFS;
+			}
+		}
+	}
+
+	if (!sp_found) {
+		int ret;
+
+		log_info("[FFA] No partition found. Querying framework ...\n");
+
+		ret = ffa_query_partitions_info(dev, &part_uuid, &sp_found);
+
+		if (ret == 0) {
+			if (!fill_data) {
+				*sp_count = sp_found;
+
+				log_info("[FFA] Number of partition(s) matching the UUID: %d\n",
+					 sp_found);
+			} else {
+				/*
+				 * If SPs data detected, they are already in the private data
+				 * structure, retry searching SP data again to return them
+				 *  to the caller
+				 */
+				if (sp_found)
+					ret = ffa_get_partitions_info(dev, uuid_str, sp_count,
+								      buffer);
+				else
+					ret = -ENODATA;
+			}
+		}
+
+		return ret;
+	}
+
+	/* Partition(s) found */
+	if (!fill_data)
+		*sp_count = sp_found;
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info() - Queries and saves all secure partitions data
+ * @dev: The arm_ffa bus device
+ *
+ * This function invokes FFA_PARTITION_INFO_GET FF-A
+ * function to query from secure world all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in the
+ * resident private data structure and we keep the UUID field empty
+ * (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * This function is called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(struct udevice *dev)
+{
+	return ffa_query_partitions_info(dev, NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The arm_ffa bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_msg_send_direct_req(struct udevice *dev, u16 dst_part_id,
+				   struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u64 req_mode, resp_mode;
+	struct ffa_priv *priv = NULL;
+
+	if (!dev)
+		return -ENODEV;
+
+	priv = dev_get_priv(dev);
+
+	if (!priv || !priv->dscvry_info.invoke_ffa_fn)
+		return -EINVAL;
+
+	/* No partition installed */
+	if (!priv->partitions.count || !priv->partitions.descs)
+		return -ENODEV;
+
+	if (is_smc64) {
+		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+	} else {
+		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
+	}
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = req_mode,
+			.a1 = PREP_SELF_ENDPOINT_ID(priv->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == resp_mode) {
+		/* Message sent with response extract the return data */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_try_discovery() - performs FF-A discovery
+ * Tries 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:
+ *
+ * true on success. Otherwise, false.
+ */
+bool ffa_try_discovery(void)
+{
+	int ret;
+
+	log_info("[FFA] trying FF-A framework discovery\n");
+
+	ret = ffa_set_smc_conduit();
+	if (ret)
+		return false;
+
+	ret = ffa_get_version();
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/**
+ * __arm_ffa_fn_smc() - 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 low level SMC assembly function
+ */
+void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * ffa_bus_is_supported() - FF-A discovery callback
+ * @invoke_fn: legacy SMC invoke function (not used)
+ *
+ * This function performs FF-A discovery by calling ffa_try_discovery().
+ * Discovery is performed by querying the FF-A framework version from
+ * secure world using the FFA_VERSION ABI.
+ *
+ * The FF-A driver is registered as an SMCCC feature driver. So, features discovery
+ * callbacks are called by the PSCI driver (PSCI device is the SMCCC features
+ * root device).
+ *
+ * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
+ * So, the legacy SMC invocation is not used.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static bool ffa_bus_is_supported(void (*invoke_fn)(unsigned long a0, unsigned long a1,
+						   unsigned long a2, unsigned long a3,
+						   unsigned long a4, unsigned long a5,
+						   unsigned long a6, unsigned long a7,
+						   struct arm_smccc_res *res))
+{
+	return ffa_try_discovery();
+}
+
+/* Registering the FF-A driver as an SMCCC feature driver */
+
+ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
+	.driver_name = FFA_DRV_NAME,
+	.is_supported = ffa_bus_is_supported,
+};
+
+/**
+ * ffa_set_smc_conduit() - Set the SMC conduit
+ *
+ * This function selects the SMC conduit by setting the driver invoke function
+ * to SMC assembly function
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_smc_conduit(void)
+{
+	dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc;
+
+	log_info("[FFA] Conduit is SMC\n");
+
+	return 0;
+}
+
+/**
+ * ffa_devm_alloc_priv() - allocate FF-A driver private data
+ * @dev: The FF-A bus device
+ *
+ * This function dynamically allocates with devres the private data structure
+ * which contains all the FF-A data. Then, register the structure with the DM.
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_devm_alloc_priv(struct udevice *dev)
+{
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	if (!priv) {
+		priv = devm_kmalloc(dev, sizeof(struct ffa_priv), __GFP_ZERO);
+		if (!priv) {
+			log_err("[FFA] can not allocate FF-A main data structure\n");
+			return -ENOMEM;
+		}
+		dev_set_priv(dev, priv);
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_probe() - The driver probe function
+ * @dev:	the FF-A bus device (arm_ffa)
+ *
+ * Probing is triggered on demand by clients searching for the uclass.
+ * At probe level the following actions are done:
+ *	- allocating private data (priv) with devres
+ *	- updating priv with discovery information
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in the private data structure (priv).
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_probe(struct udevice *dev)
+{
+	int ret;
+	struct ffa_priv *priv = NULL;
+
+	ret = ffa_devm_alloc_priv(dev);
+	if (ret)
+		return ret;
+
+	/* The data is dynamically allocated, managed by devres */
+	priv = dev_get_priv(dev);
+
+	priv->dscvry_info = dscvry_info;
+
+	ret = ffa_get_endpoint_id(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_cache_partitions_info(dev);
+	if (ret) {
+		ffa_unmap_rxtx_buffers(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_remove() - The driver remove function
+ * @dev:	the arm_ffa device
+ * Making sure the RX/TX buffers are unmapped and freed when the device is removed.
+ * No need to free the private data structure because devres takes care of that.
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_remove(struct udevice *dev)
+{
+	log_info("[FFA] removing the device\n");
+
+	ffa_unmap_rxtx_buffers(dev);
+	dev_set_priv(dev, NULL);
+
+	return 0;
+}
+
+/**
+ * ffa_unbind() - The driver unbind function
+ * @dev:	the arm_ffa device
+ * Making sure the RX/TX buffers are unmapped and freed when the device is unbound.
+ * No need to free the private data structure because devres takes care of that.
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_unbind(struct udevice *dev)
+{
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	log_info("[FFA] unbinding the device\n");
+
+	if (priv)
+		ffa_unmap_rxtx_buffers(dev);
+
+	return 0;
+}
+
+/* FF-A driver operations */
+
+static const struct ffa_bus_ops ffa_ops = {
+	.partition_info_get = ffa_get_partitions_info,
+	.sync_send_receive = ffa_msg_send_direct_req,
+	.rxtx_unmap = ffa_unmap_rxtx_buffers,
+};
+
+/* Declaring the FF-A driver under UCLASS_FFA */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.flags		= DM_REMOVE_OS_PREPARE,
+	.probe		= ffa_probe,
+	.remove	= ffa_remove,
+	.unbind	= ffa_unbind,
+	.ops		= &ffa_ops,
+};
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..69f3c51080
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,88 @@
+/* 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 __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct ffa_send_direct_data {
+	unsigned long data0; /* w3/x3 */
+	unsigned long data1; /* w4/x4 */
+	unsigned long data2; /* w5/x5 */
+	unsigned long data3; /* w6/x6 */
+	unsigned long data4; /* w7/x7 */
+};
+
+struct udevice;
+
+/**
+ * struct ffa_bus_ops - The driver operations structure
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
+				  u32 *sp_count, struct ffa_partition_info *buffer);
+	int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg,
+				 bool is_smc64);
+	int (*rxtx_unmap)(struct udevice *dev);
+};
+
+/* The device driver and the Uclass driver public functions */
+
+/**
+ * ffa_bus_get_ops() - bus driver operations getter
+ * @dev:	the arm_ffa device
+ * Returns a pointer to the FF-A driver ops field.
+ * Return:
+ * The ops pointer on success, NULL on failure.
+ */
+const struct ffa_bus_ops *ffa_bus_get_ops(struct udevice *dev);
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 33e43c20db..df77c7da58 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,11 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -55,6 +60,7 @@ enum uclass_id {
 	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v9 05/10] arm_ffa: introduce armffa command
  2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                       ` (3 preceding siblings ...)
  2023-03-10 14:10                                                                                     ` [PATCH v9 04/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
@ 2023-03-10 14:10                                                                                     ` Abdellatif El Khlifi
  2023-03-10 20:49                                                                                       ` Simon Glass
  2023-03-10 14:10                                                                                     ` [PATCH v9 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
                                                                                                       ` (5 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-10 14:10 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

Provide armffa command showcasing the use of the FF-A driver

armffa is a command showcasing how to use the FF-A driver and how to invoke
its operations. This provides a guidance to the client developers on how to
call the FF-A bus interfaces. The command also allows to gather secure
partitions information and ping these  partitions. The command is also
helpful in testing the communication with secure partitions.

For more details please refer to the command documentation [1].

[1]: doc/usage/cmd/armffa.rst

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>

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

v9:

* remove manual FF-A discovery and use DM
* use DM class APIs to probe and interact with the FF-A bus
* add doc/usage/cmd/armffa.rst

v8:

* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* adapt do_ffa_dev_list() following the recent update on
  uclass_first_device/uclass_next_device functions (they return void now)
* set armffa command to use 64-bit direct messaging

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

 MAINTAINERS                      |   2 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   2 +
 cmd/armffa.c                     | 264 +++++++++++++++++++++++++++++++
 doc/usage/cmd/armffa.rst         | 118 ++++++++++++++
 doc/usage/index.rst              |   1 +
 drivers/firmware/arm-ffa/Kconfig |   1 +
 7 files changed, 398 insertions(+)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/usage/cmd/armffa.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 1dfa23c1f0..18e9c2ce99 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,7 +269,9 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+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
 
diff --git a/cmd/Kconfig b/cmd/Kconfig
index a3512836c1..f24c52def4 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -934,6 +934,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the Arm FF-A driver
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index 2d8bb4fc05..a59ab55ad0 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,8 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
 obj-$(CONFIG_CMD_AES) += aes.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..f6c017542d
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,264 @@
+// 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 <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+#include <asm/io.h>
+
+/**
+ * do_ffa_getpart() - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver partition_info_get operation
+ * which implements FFA_PARTITION_INFO_GET ABI to retrieve the data.
+ * The input UUID string is expected to be in big endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx;
+	struct udevice *dev = NULL;
+	struct ffa_bus_ops *ffa_ops = NULL;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &dev);
+	if (!dev) {
+		log_err("[FFA] Cannot find FF-A bus device\n");
+		return -ENODEV;
+	}
+
+	ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(dev);
+	if (!ffa_ops) {
+		log_err("[FFA] Invalid FF-A ops\n");
+		return -EINVAL;
+	}
+
+	/* Mode 1: getting the number of secure partitions */
+	ret = ffa_ops->partition_info_get(dev, argv[0], &count, NULL);
+	if (ret != 0) {
+		log_err("[FFA] Failure in querying partitions count (error code: %d)\n", ret);
+		return ret;
+	}
+
+	if (!count) {
+		log_info("[FFA] No secure partition found\n");
+		return ret;
+	}
+
+	/*
+	 * Pre-allocate a buffer to be filled by the driver
+	 * with ffa_partition_info structs
+	 */
+
+	log_info("[FFA] Pre-allocating %d partition(s) info structures\n", count);
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+
+	ret = ffa_ops->partition_info_get(dev, argv[0], &count, parts_info);
+	if (ret != 0) {
+		log_err("[FFA] Failure in querying partition(s) info (error code: %d)\n", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/* SPs found , show the partition information */
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		log_info("[FFA] Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x\n",
+			 parts_info[info_idx].id,
+			 parts_info[info_idx].exec_ctxt,
+			 parts_info[info_idx].properties);
+	}
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * do_ffa_ping() - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function sends data to the secure partition which the ID is provided
+ * as an argument. The function uses the arm_ffa driver sync_send_receive operation
+ * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+	struct udevice *dev = NULL;
+	struct ffa_bus_ops *ffa_ops = NULL;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	errno = 0;
+	part_id = strtoul(argv[0], NULL, 16);
+
+	if (errno) {
+		log_err("[FFA] Invalid partition ID\n");
+		return -EINVAL;
+	}
+
+	uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &dev);
+	if (!dev) {
+		log_err("[FFA] Cannot find FF-A bus device\n");
+		return -ENODEV;
+	}
+
+	ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(dev);
+	if (!ffa_ops) {
+		log_err("[FFA] Invalid FF-A ops\n");
+		return -EINVAL;
+	}
+
+	ret = ffa_ops->sync_send_receive(dev, part_id, &msg, 1);
+	if (!ret) {
+		u8 cnt;
+
+		log_info("[FFA] SP response:\n[LSB]\n");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			log_info("[FFA] 0x%llx\n", ((u64 *)&msg)[cnt]);
+	} else {
+		log_err("[FFA] Sending direct request error (%d)\n", ret);
+	}
+
+	return ret;
+}
+
+/**
+ *do_ffa_devlist() - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the devices belonging to the UCLASS_FFA
+ * class.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev = NULL;
+	int i;
+
+	log_info("[FFA] FF-A uclass entries:\n");
+
+	for (i = 0, uclass_first_device(UCLASS_FFA, &dev);
+	     dev;
+	     uclass_next_device(&dev), i++) {
+		log_info("[FFA] entry %d - instance %08x, ops %08x, plat %08x\n",
+			 i,
+			 (u32)map_to_sysmem(dev),
+			 (u32)map_to_sysmem(dev->driver->ops),
+			 (u32)map_to_sysmem(dev_get_plat(dev)));
+	}
+
+	return 0;
+}
+
+static struct cmd_tbl armffa_commands[] = {
+	U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_getpart, "", ""),
+	U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_ping, "", ""),
+	U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_devlist, "", ""),
+};
+
+/**
+ * do_armffa() - the armffa command main function
+ * @cmdtp:	Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function identifies which armffa subcommand to run.
+ * Then, it makes sure the arm_ffa device is probed and
+ * ready for use.
+ * Then, it runs the subcommand.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct cmd_tbl *armffa_cmd;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
+
+	argc -= 2;
+	argv += 2;
+
+	if (!armffa_cmd || argc > armffa_cmd->maxargs)
+		return CMD_RET_USAGE;
+
+	if (IS_ENABLED(CONFIG_SANDBOX_FFA)) {
+		struct udevice *sdx_dev = NULL;
+		/*  Probe the FF-A sandbox driver, then bind the FF-A bus driver */
+		uclass_get_device_by_name(UCLASS_FFA, "sandbox_arm_ffa", &sdx_dev);
+		if (!sdx_dev) {
+			log_err("[FFA] Cannot find FF-A sandbox device\n");
+			return -ENODEV;
+		}
+	}
+
+	ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
+
+	return cmd_process_error(armffa_cmd, ret);
+}
+
+U_BOOT_CMD(armffa, 4, 1, do_armffa,
+	   "Arm FF-A operations test command",
+	   "getpart <partition UUID>\n"
+	   "	 - lists the partition(s) info\n"
+	   "ping <partition ID>\n"
+	   "	 - sends a data pattern to the specified partition\n"
+	   "devlist\n"
+	   "	 - displays instance info of FF-A devices (the bus and its associated sandbox\n");
diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
new file mode 100644
index 0000000000..91f89971d1
--- /dev/null
+++ b/doc/usage/cmd/armffa.rst
@@ -0,0 +1,118 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+armffa command
+==============
+
+Synopsis
+--------
+
+::
+
+   armffa [sub-command] [arguments]
+
+   sub-commands:
+
+        getpart [partition UUID]
+
+            lists the partition(s) info
+
+        ping [partition ID]
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays instance info of FF-A devices (the bus and its associated sandbox)
+
+Description
+-----------
+
+armffa is a command showcasing how to use the FF-A driver and how to invoke its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
+
+The command also allows to gather secure partitions information and ping these  partitions.
+
+The command is also helpful in testing the communication with secure partitions.
+
+Example
+-------
+
+The following examples are run on Corstone-1000 platform with debug logs enabled.
+
+* ping
+
+::
+
+   corstone1000# armffa ping 0x8003
+   [FFA] endpoint ID is 0
+   [FFA] Using 1 4KB page(s) for RX/TX buffers size
+   [FFA] RX buffer at virtual address 00000000fdf48000
+   [FFA] TX buffer at virtual address 00000000fdf4a000
+   [FFA] RX/TX buffers mapped
+   [FFA] Reading partitions data from the RX buffer
+   [FFA] Partition ID 8001 : info cached
+   [FFA] Partition ID 8002 : info cached
+   [FFA] Partition ID 8003 : info cached
+   [FFA] 3 partition(s) found and cached
+   [FFA] SP response:
+   [LSB]
+   [FFA] 0xfffffffe
+   [FFA] 0x0
+   [FFA] 0x0
+   [FFA] 0x0
+   [FFA] 0x0
+
+* ping (failure case)
+
+::
+
+   corstone1000# armffa ping 0x1234
+   [FFA] Sending direct request error (-22)
+   Command 'ping' failed: Error -22
+
+* getpart
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
+   [FFA] Preparing for checking partitions count
+   [FFA] Searching partitions using the provided UUID
+   [FFA] No partition found. Querying framework ...
+   [FFA] Reading partitions data from the RX buffer
+   [FFA] Number of partition(s) matching the UUID: 1
+   [FFA] Pre-allocating 1 partition(s) info structures
+   [FFA] Preparing for filling partitions info
+   [FFA] Searching partitions using the provided UUID
+   [FFA] Partition ID 8003 matches the provided UUID
+   [FFA] Partition: id = 0x8003 , exec_ctxt 0x1 , properties 0x3
+
+* getpart (failure case)
+
+::
+
+    corstone1000# armffa getpart ed32d533-4209-99e6-2d72-cdd998a79cc0
+    [FFA] Preparing for checking partitions count
+    [FFA] Searching partitions using the provided UUID
+    [FFA] No partition found. Querying framework ...
+    [FFA] INVALID_PARAMETERS: Unrecognized UUID
+    [FFA] Failure in querying partitions count (error code: -22)
+    Command 'getpart' failed: Error -22
+
+* devlist
+
+::
+
+   corstone1000# armffa devlist
+   [FFA] FF-A uclass entries:
+   [FFA] entry 0 - instance fdf40c50, ops fffc0408, plat 00000000
+
+Configuration
+-------------
+
+The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
+
+Return value
+------------
+
+The return value $? is 0 (true) on success and a negative error code on failure.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 840c20c934..f1b9335cb1 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -21,6 +21,7 @@ Shell commands
 
    cmd/acpi
    cmd/addrmap
+   cmd/armffa
    cmd/askenv
    cmd/base
    cmd/bdinfo
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index e5b2912201..2cfd7ef5fc 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
 	depends on DM && ARM64
 	select ARM_SMCCC
 	select ARM_SMCCC_FEATURES
+	imply CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v9 06/10] arm_ffa: introduce the FF-A Sandbox driver
  2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                       ` (4 preceding siblings ...)
  2023-03-10 14:10                                                                                     ` [PATCH v9 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-03-10 14:10                                                                                     ` Abdellatif El Khlifi
  2023-03-10 20:49                                                                                       ` Simon Glass
  2023-03-10 14:10                                                                                     ` [PATCH v9 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                                                                       ` (4 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-10 14:10 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

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>

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

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

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

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

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

v1: introduce the sandbox driver

 MAINTAINERS                                   |   1 +
 arch/sandbox/dts/sandbox.dtsi                 |   4 +
 arch/sandbox/dts/test.dts                     |   4 +
 configs/sandbox64_defconfig                   |   2 +
 configs/sandbox_defconfig                     |   2 +
 doc/arch/arm64.ffa.rst                        |   4 +
 doc/arch/sandbox/sandbox.rst                  |   1 +
 drivers/firmware/arm-ffa/Kconfig              |  11 +-
 drivers/firmware/arm-ffa/Makefile             |   1 +
 drivers/firmware/arm-ffa/core.c               |  36 +-
 drivers/firmware/arm-ffa/sandbox.c            | 610 ++++++++++++++++++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   | 129 ++++
 include/arm_ffa.h                             |   5 +-
 include/sandbox_arm_ffa.h                     | 124 ++++
 14 files changed, 928 insertions(+), 6 deletions(-)
 create mode 100644 drivers/firmware/arm-ffa/sandbox.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
 create mode 100644 include/sandbox_arm_ffa.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 18e9c2ce99..2b9d33e964 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -274,6 +274,7 @@ 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..059c273277 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -445,6 +445,10 @@
 	thermal {
 		compatible = "sandbox,thermal";
 	};
+
+	sandbox_arm_ffa {
+		compatible = "sandbox,arm_ffa";
+	};
 };
 
 &cros_ec {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index d72d7a567a..11dc6ed0d9 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1802,6 +1802,10 @@
 		compatible = "u-boot,fwu-mdata-gpt";
 		fwu-mdata-store = <&mmc0>;
 	};
+
+	sandbox_arm_ffa {
+		compatible = "sandbox,arm_ffa";
+	};
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index ccbc18aad0..35d4676cf7 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -259,3 +259,5 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
+CONFIG_SANDBOX_FFA=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index a0fbdad20a..8aab8dda31 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -336,3 +336,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/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 8fad9ef3d0..555ee9a6ae 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -64,6 +64,10 @@ CONFIG_ARM_FFA_TRANSPORT
     Enables the FF-A bus driver. Turn this on if you want to use FF-A
     communication.
 
+CONFIG_SANDBOX_FFA
+    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
+    Sandbox and provides functional tests for FF-A.
+
 FF-A ABIs under the hood
 ---------------------------------------
 
diff --git a/doc/arch/sandbox/sandbox.rst b/doc/arch/sandbox/sandbox.rst
index cd7f8a2cb0..c5df372e00 100644
--- a/doc/arch/sandbox/sandbox.rst
+++ b/doc/arch/sandbox/sandbox.rst
@@ -200,6 +200,7 @@ Supported Drivers
 
 U-Boot sandbox supports these emulations:
 
+- Arm FF-A
 - Block devices
 - Chrome OS EC
 - GPIO
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index 2cfd7ef5fc..b5430eb6f4 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
@@ -32,3 +32,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 c8d83b4bc9..d22c1ba609 100644
--- a/drivers/firmware/arm-ffa/Makefile
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -6,3 +6,4 @@
 #   Abdellatif El Khlifi <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/core.c b/drivers/firmware/arm-ffa/core.c
index 2210f5343c..0d2e6ff0d4 100644
--- a/drivers/firmware/arm-ffa/core.c
+++ b/drivers/firmware/arm-ffa/core.c
@@ -1042,6 +1042,7 @@ bool ffa_try_discovery(void)
 	return true;
 }
 
+#if !CONFIG_IS_ENABLED(SANDBOX_FFA)
 /**
  * __arm_ffa_fn_smc() - SMC wrapper
  * @args: FF-A ABI arguments to be copied to Xn registers
@@ -1069,6 +1070,7 @@ void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
  * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
  * So, the legacy SMC invocation is not used.
  *
+ * In Sandbox mode sandbox_arm_ffa is used to test arm_ffa driver.
  * Return:
  *
  * 0 on success. Otherwise, failure
@@ -1088,6 +1090,30 @@ ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
 	.driver_name = FFA_DRV_NAME,
 	.is_supported = ffa_bus_is_supported,
 };
+#else
+/* SANDBOX_FFA */
+
+/**
+ * ffa_bind() - The driver bind function
+ * @dev:	the arm_ffa device
+ * When using sandbox tries to discover the emulated FF-A bus.
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_bind(struct udevice *dev)
+{
+	bool ret;
+
+	log_info("[FFA] binding the device\n");
+
+	ret = ffa_try_discovery();
+	if (ret)
+		return 0;
+	else
+		return -ENODEV;
+}
+#endif
 
 /**
  * ffa_set_smc_conduit() - Set the SMC conduit
@@ -1101,7 +1127,12 @@ ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
  */
 static int ffa_set_smc_conduit(void)
 {
-	dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc;
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+		dscvry_info.invoke_ffa_fn = sandbox_arm_ffa_smccc_smc;
+		log_info("[FFA] Using SMC emulation\n");
+#else
+		dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc;
+#endif
 
 	log_info("[FFA] Conduit is SMC\n");
 
@@ -1246,4 +1277,7 @@ U_BOOT_DRIVER(arm_ffa) = {
 	.remove	= ffa_remove,
 	.unbind	= ffa_unbind,
 	.ops		= &ffa_ops,
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+	.bind		= ffa_bind,
+#endif
 };
diff --git a/drivers/firmware/arm-ffa/sandbox.c b/drivers/firmware/arm-ffa/sandbox.c
new file mode 100644
index 0000000000..84c2fc929f
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox.c
@@ -0,0 +1,610 @@
+// 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 <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+#include "sandbox_arm_ffa_priv.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* The partitions (SPs) table */
+static struct ffa_partition_desc sandbox_partitions[SANDBOX_PARTITIONS_CNT] = {
+	{
+		.info = { .id = SANDBOX_SP1_ID, .exec_ctxt = 0x5687, .properties = 0x89325621 },
+		.sp_uuid = {
+			.a1 = SANDBOX_SERVICE1_UUID_A1,
+			.a2 = SANDBOX_SERVICE1_UUID_A2,
+			.a3 = SANDBOX_SERVICE1_UUID_A3,
+			.a4 = SANDBOX_SERVICE1_UUID_A4,
+		}
+	},
+	{
+		.info = { .id = SANDBOX_SP2_ID, .exec_ctxt = 0x9587, .properties = 0x45325621 },
+		.sp_uuid = {
+			.a1 = SANDBOX_SERVICE2_UUID_A1,
+			.a2 = SANDBOX_SERVICE2_UUID_A2,
+			.a3 = SANDBOX_SERVICE2_UUID_A3,
+			.a4 = SANDBOX_SERVICE2_UUID_A4,
+		}
+	},
+	{
+		.info = { .id = SANDBOX_SP3_ID, .exec_ctxt = 0x7687, .properties = 0x23325621 },
+		.sp_uuid = {
+			.a1 = SANDBOX_SERVICE1_UUID_A1,
+			.a2 = SANDBOX_SERVICE1_UUID_A2,
+			.a3 = SANDBOX_SERVICE1_UUID_A3,
+			.a4 = SANDBOX_SERVICE1_UUID_A4,
+		}
+	},
+	{
+		.info = { .id = SANDBOX_SP4_ID, .exec_ctxt = 0x1487, .properties = 0x70325621 },
+		.sp_uuid = {
+			.a1 = SANDBOX_SERVICE2_UUID_A1,
+			.a2 = SANDBOX_SERVICE2_UUID_A2,
+			.a3 = SANDBOX_SERVICE2_UUID_A3,
+			.a4 = SANDBOX_SERVICE2_UUID_A4,
+		}
+	}
+
+};
+
+/* Driver functions */
+
+/**
+ * sandbox_ffa_version() - Emulated FFA_VERSION handler function
+ * @dev:	the sandbox FF-A device
+ * @{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)
+{
+	struct sandbox_ffa_priv *priv = dev_get_priv(dev);
+
+	priv->fwk_version = FFA_VERSION_1_0;
+	res->a0 = priv->fwk_version;
+
+	/* x1-x7 MBZ */
+	memset(FFA_X1X7_MBZ_REG_START, 0, FFA_X1X7_MBZ_CNT * sizeof(unsigned long));
+
+	return 0;
+}
+
+/**
+ * sandbox_ffa_id_get() - Emulated FFA_ID_GET handler function
+ * @dev:	the sandbox FF-A device
+ * @{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)
+{
+	struct sandbox_ffa_priv *priv = dev_get_priv(dev);
+
+	res->a0 = FFA_SMC_32(FFA_SUCCESS);
+	res->a1 = 0;
+
+	priv->id = NS_PHYS_ENDPOINT_ID;
+	res->a2 = priv->id;
+
+	/* x3-x7 MBZ */
+	memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long));
+
+	return 0;
+}
+
+/**
+ * sandbox_ffa_features() - Emulated FFA_FEATURES handler function
+ * @dev:	the sandbox FF-A device
+ * @{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));
+		log_err("[FFA] [Sandbox] FF-A interface 0x%lx not implemented\n", pargs->a1);
+	}
+
+	res->a1 = 0;
+
+	return 0;
+}
+
+/**
+ * sandbox_ffa_partition_info_get() - Emulated FFA_PARTITION_INFO_GET handler function
+ * @dev:	the sandbox FF-A device
+ * @{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;
+	struct sandbox_ffa_priv *priv = dev_get_priv(dev);
+
+	res->a0 = FFA_SMC_32(FFA_ERROR);
+
+	if (!priv->pair.rxbuf) {
+		res->a2 = FFA_ERR_STAT_DENIED;
+		goto cleanup;
+	}
+
+	if (priv->pair_info.rxbuf_owned) {
+		res->a2 = FFA_ERR_STAT_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 descriptors buffer size */
+	if ((priv->pair_info.rxtx_buf_size * SZ_4K) < descs_size_bytes) {
+		res->a2 = FFA_ERR_STAT_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;
+
+		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 == 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 = (unsigned long)
+			(rxbuf_desc_info - (struct ffa_partition_info *)priv->pair.rxbuf);
+
+		/* Transfer ownership to the consumer: the non secure world */
+		priv->pair_info.rxbuf_owned = 1;
+	} else {
+		/* Unrecognized UUID */
+		res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS;
+	}
+
+cleanup:
+
+	log_err("[FFA] [Sandbox] 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(unsigned long));
+
+	return 0;
+}
+
+/**
+ * sandbox_ffa_rxtx_map() - Emulated FFA_RXTX_MAP handler function
+ * @dev:	the sandbox FF-A device
+ * @{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)
+{
+	struct sandbox_ffa_priv *priv = dev_get_priv(dev);
+
+	res->a0 = FFA_SMC_32(FFA_ERROR);
+
+	if (priv->pair.txbuf && priv->pair.rxbuf) {
+		res->a2 = FFA_ERR_STAT_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;
+		goto feedback;
+	}
+
+	if (!pargs->a1 || !pargs->a2)
+		res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS;
+	else
+		res->a2 = FFA_ERR_STAT_NO_MEMORY;
+
+	log_err("[FFA] [Sandbox] 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(unsigned long));
+
+	return 0;
+}
+
+/**
+ * sandbox_ffa_rxtx_unmap() - Emulated FFA_RXTX_UNMAP handler function
+ * @dev:	the sandbox FF-A device
+ * @{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)
+{
+	struct sandbox_ffa_priv *priv = dev_get_priv(dev);
+
+	res->a0 = FFA_SMC_32(FFA_ERROR);
+	res->a2 = FFA_ERR_STAT_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;
+		goto feedback;
+	}
+
+	log_err("[FFA] [Sandbox] 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(unsigned long));
+
+	return 0;
+}
+
+/**
+ * sandbox_ffa_rx_release() - Emulated FFA_RX_RELEASE handler function
+ * @dev:	the sandbox FF-A device
+ * @{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)
+{
+	struct sandbox_ffa_priv *priv = dev_get_priv(dev);
+
+	if (!priv->pair_info.rxbuf_owned) {
+		res->a0 = FFA_SMC_32(FFA_ERROR);
+		res->a2 = FFA_ERR_STAT_DENIED;
+	} else {
+		priv->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
+ * @dev:	the sandbox_arm_ffa device
+ * @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(struct udevice *dev, u16 part_id)
+{
+	u32 descs_cnt;
+	struct sandbox_ffa_priv *priv = dev_get_priv(dev);
+
+	for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++)
+		if (priv->partitions.descs[descs_cnt].info.id == part_id)
+			return 1;
+
+	return 0;
+}
+
+/**
+ * sandbox_ffa_msg_send_direct_req() - Emulated FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev:	the sandbox FF-A device
+ * @{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;
+	struct sandbox_ffa_priv *priv = dev_get_priv(dev);
+
+	part_id = GET_DST_SP_ID(pargs->a1);
+
+	if ((GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id) ||
+	    !sandbox_ffa_sp_valid(dev, part_id) || pargs->a2) {
+		res->a0 = FFA_SMC_32(FFA_ERROR);
+		res->a1 = 0;
+		res->a2 = 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(priv->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_rxbuf_flags() - Reading the mapping/ownership flags
+ * @dev:	the sandbox_arm_ffa device
+ * @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(struct udevice *dev, u32 queried_func_id,
+				       struct ffa_sandbox_data *func_data)
+{
+	struct sandbox_ffa_priv *priv = dev_get_priv(dev);
+
+	if (!func_data)
+		return -EINVAL;
+
+	if (!func_data->data0 || func_data->data0_size != sizeof(u8))
+		return -EINVAL;
+
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+	case FFA_RXTX_UNMAP:
+		*((u8 *)func_data->data0) = priv->pair_info.rxbuf_mapped;
+		return 0;
+	case FFA_RX_RELEASE:
+		*((u8 *)func_data->data0) = priv->pair_info.rxbuf_owned;
+		return 0;
+	default:
+		log_err("[FFA] [Sandbox] The querried  FF-A interface flag (%d) undefined\n",
+			queried_func_id);
+		return -EINVAL;
+	}
+}
+
+/**
+ * sandbox_ffa_query_core_state() - The driver dispatcher function
+ * @dev:	the sandbox_arm_ffa device
+ * @queried_func_id:	The FF-A function to be queried
+ * @func_data:  Pointer to the FF-A function arguments container structure
+ *
+ * Queries the status of FF-A ABI specified in the input argument.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int sandbox_ffa_query_core_state(struct udevice *dev, u32 queried_func_id,
+				 struct ffa_sandbox_data *func_data)
+{
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+	case FFA_RXTX_UNMAP:
+	case FFA_RX_RELEASE:
+		return sandbox_ffa_get_rxbuf_flags(dev, queried_func_id, func_data);
+	default:
+		log_err("[FFA] [Sandbox] 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
+ *
+ * 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;
+	struct udevice *dev = NULL;
+
+	uclass_get_device_by_name(UCLASS_FFA, "sandbox_arm_ffa", &dev);
+	if (!dev) {
+		log_err("[FFA] [Sandbox] Cannot find FF-A sandbox device\n");
+		return;
+	}
+
+	switch (args.a0) {
+	case FFA_SMC_32(FFA_VERSION):
+		ret = sandbox_ffa_version(dev, &args, res);
+		break;
+	case FFA_SMC_32(FFA_PARTITION_INFO_GET):
+		ret = sandbox_ffa_partition_info_get(dev, &args, res);
+		break;
+	case FFA_SMC_32(FFA_RXTX_UNMAP):
+		ret = sandbox_ffa_rxtx_unmap(dev, &args, res);
+		break;
+	case FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ):
+		ret = sandbox_ffa_msg_send_direct_req(dev, &args, res);
+		break;
+	case FFA_SMC_32(FFA_ID_GET):
+		ret = sandbox_ffa_id_get(dev, &args, res);
+		break;
+	case FFA_SMC_32(FFA_FEATURES):
+		ret = sandbox_ffa_features(dev, &args, res);
+		break;
+	case FFA_SMC_64(FFA_RXTX_MAP):
+		ret = sandbox_ffa_rxtx_map(dev, &args, res);
+		break;
+	case FFA_SMC_32(FFA_RX_RELEASE):
+		ret = sandbox_ffa_rx_release(dev, &args, res);
+		break;
+	default:
+		log_err("[FFA] [Sandbox] Undefined FF-A interface (0x%lx)\n", args.a0);
+	}
+
+	if (ret != 0)
+		log_err("[FFA] [Sandbox] FF-A ABI internal failure (%d)\n", ret);
+}
+
+/**
+ * sandbox_ffa_probe() - The driver probe function
+ * @dev:	the sandbox_arm_ffa device
+ *
+ * Binds the FF-A bus driver and sets the sandbox device as the FF-A bus device parent
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_probe(struct udevice *dev)
+{
+	struct udevice *child_dev = NULL;
+	int ret;
+
+	ret = device_bind_driver(dev, FFA_DRV_NAME, FFA_DRV_NAME, &child_dev);
+	if (ret) {
+		pr_err("%s was not bound: %d, aborting\n", FFA_DRV_NAME, ret);
+		return -ENODEV;
+	}
+
+	dev_set_parent_plat(child_dev, dev_get_plat(dev));
+
+	return 0;
+}
+
+static const struct udevice_id sandbox_ffa_id[] = {
+	{ "sandbox,arm_ffa", 0 },
+	{ },
+};
+
+/* Declaring the sandbox_arm_ffa driver under UCLASS_FFA */
+U_BOOT_DRIVER(sandbox_arm_ffa) = {
+	.name		= FFA_SANDBOX_DRV_NAME,
+	.of_match = sandbox_ffa_id,
+	.id		= UCLASS_FFA,
+	.probe		= sandbox_ffa_probe,
+	.priv_auto	= sizeof(struct sandbox_ffa_priv),
+};
diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
new file mode 100644
index 0000000000..c35d80de16
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
@@ -0,0 +1,129 @@
+/* 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 <sandbox_arm_ffa.h>
+#include "arm_ffa_priv.h"
+
+/* This header is exclusively used by the Sandbox FF-A driver and sandbox tests */
+
+/* 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
+
+/* 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 secure partitions emulated by the FF-A sandbox driver */
+#define SANDBOX_PARTITIONS_CNT (4)
+
+/* Binary data of services UUIDs emulated by the FF-A sandbox driver */
+
+/* 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_priv - 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_priv {
+	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(struct udevice *dev, \
+							      ffa_value_t *pargs, ffa_value_t *res)
+
+#endif
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
index 69f3c51080..70a9eefae6 100644
--- a/include/arm_ffa.h
+++ b/include/arm_ffa.h
@@ -12,8 +12,9 @@
 #include <linux/printk.h>
 
 /*
- * This header is public. It can be used by clients to access
- * data structures and definitions they need
+ * This header is used to access FF-A data structures
+ * and definitions. The header is used by the FF-A core driver, clients,
+ * sandbox driver, sandbox tests, armffa command
  */
 
 /*
diff --git a/include/sandbox_arm_ffa.h b/include/sandbox_arm_ffa.h
new file mode 100644
index 0000000000..3d99b6b8fa
--- /dev/null
+++ b/include/sandbox_arm_ffa.h
@@ -0,0 +1,124 @@
+/* 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 the sandbox driver declarations
+ * needed by FF-A driver, armffa command and sandbox tests
+ */
+
+/* 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))
+
+/**
+ * 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 strings of services emulated by the FF-A sandbox driver */
+#define SANDBOX_SERVICE1_UUID	"ed32d533-4209-99e6-2d72-cdd998a79cc0"
+#define SANDBOX_SERVICE2_UUID	"ed32d544-4209-99e6-2d72-cdd998a79cc0"
+
+/* IDs of secure partitions (SPs) emulated by the FF-A sandbox driver */
+#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 - 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() - The driver dispatcher function
+ * @dev:	the sandbox_arm_ffa device
+ * @queried_func_id:	The FF-A function to be queried
+ * @func_data:  Pointer to the FF-A function arguments container structure
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+int sandbox_ffa_query_core_state(struct udevice *dev, u32 queried_func_id,
+				 struct ffa_sandbox_data *func_data);
+
+/**
+ * sandbox_arm_ffa_smccc_smc() - FF-A SMC call emulation
+ * @args:	the SMC call arguments
+ * @res:	the SMC call returned data
+ * 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);
+
+#endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v9 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                       ` (5 preceding siblings ...)
  2023-03-10 14:10                                                                                     ` [PATCH v9 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
@ 2023-03-10 14:10                                                                                     ` Abdellatif El Khlifi
  2023-03-10 20:49                                                                                       ` Simon Glass
  2023-03-10 14:10                                                                                     ` [PATCH v9 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                                                                       ` (3 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-10 14:10 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

Add functional test cases for the FF-A core driver

These tests rely on the FF-A Sandbox driver which helps in
 inspecting the FF-A core driver.

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>

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

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

v8:

  * update partition_info_get() second argument to be an SP count
  * pass NULL device pointer to the FF-A bus discovery and operations

v7: set the tests to use 64-bit direct messaging

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

v1: introduce sandbox tests

 MAINTAINERS      |   1 +
 test/dm/Makefile |   2 +
 test/dm/ffa.c    | 380 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 383 insertions(+)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 2b9d33e964..6939b832e4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -275,6 +275,7 @@ F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/sandbox_arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 7a79b6e1a2..b554b170db 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -85,6 +86,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_SANDBOX_FFA) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..d978feda72
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,380 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <console.h>
+#include <dm.h>
+#include <sandbox_arm_ffa.h>
+#include "../../drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h"
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Macros */
+
+#define LOG_MSG_SZ (100)
+#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
+
+/* Functional tests for the UCLASS_FFA */
+
+static int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
+{
+	char cmd[LOG_CMD_SZ] = {0};
+
+	console_record_reset();
+
+	snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
+	run_command(cmd, 0);
+
+	ut_assert_console_end();
+
+	return 0;
+}
+
+static int check_fwk_version(struct ffa_priv *priv, struct sandbox_ffa_priv *sdx_priv,
+			     struct unit_test_state *uts)
+{
+	if (priv->dscvry_info.fwk_version != sdx_priv->fwk_version) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: framework version: core = 0x%x , sandbox  = 0x%x", __func__,
+			 priv->dscvry_info.fwk_version,
+			sdx_priv->fwk_version);
+
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return 0;
+}
+
+static int check_endpoint_id(struct ffa_priv *priv, struct unit_test_state *uts)
+{
+	if (priv->id) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: endpoint id: core = 0x%x", __func__, priv->id);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return 0;
+}
+
+static int check_rxtxbuf(struct ffa_priv *priv, struct unit_test_state *uts)
+{
+	if (!priv->pair.rxbuf && priv->pair.txbuf) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = %p txbuf = %p", __func__,
+			 priv->pair.rxbuf,
+			 priv->pair.txbuf);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return 0;
+}
+
+static int check_features(struct ffa_priv *priv, struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	if (priv->pair.rxtx_min_pages != RXTX_4K &&
+	    priv->pair.rxtx_min_pages != RXTX_16K &&
+	    priv->pair.rxtx_min_pages != RXTX_64K) {
+		snprintf(msg,
+			 LOG_MSG_SZ,
+			 "[%s]: Error: FFA_RXTX_MAP features = 0x%lx",
+			 __func__,
+			 priv->pair.rxtx_min_pages);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+
+	return 0;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+	{
+		if (rxbuf_mapped)
+			return 0;
+		break;
+	}
+	case FFA_RXTX_UNMAP:
+	{
+		if (!rxbuf_mapped)
+			return 0;
+		break;
+	}
+	default:
+		return CMD_RET_FAILURE;
+	}
+
+	snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__,
+		 (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP"));
+	dm_test_ffa_log(uts, msg);
+
+	return CMD_RET_FAILURE;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	if (rxbuf_owned) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return 0;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg = {0};
+	u8 cnt;
+	struct udevice *ffa_dev = NULL;
+	struct ffa_bus_ops *ffa_ops = NULL;
+
+	uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev);
+	ut_assertok(!ffa_dev);
+
+	ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev);
+	ut_assertok(!ffa_ops);
+
+	ut_assertok(ffa_ops->sync_send_receive(ffa_dev, part_id, &msg, 1));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_assertok(((u64 *)&msg)[cnt] != 0xffffffffffffffff);
+
+	return 0;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct sandbox_ffa_priv *sdx_priv,
+				     struct unit_test_state *uts)
+{
+	u32 count = 0;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx, exp_info_idx;
+	int ret;
+	struct udevice *ffa_dev = NULL;
+	struct ffa_bus_ops *ffa_ops = NULL;
+
+	uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev);
+	ut_assertok(!ffa_dev);
+
+	ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev);
+	ut_assertok(!ffa_ops);
+
+	/* Get from the driver the count of the SPs matching the UUID */
+	ret = ffa_ops->partition_info_get(ffa_dev, service_uuid, &count, NULL);
+	/* Make sure partitions are detected */
+	ut_assertok(ret != 0);
+	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
+
+	/* Pre-allocate a buffer to be filled by the driver with ffa_partition_info structs */
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	ut_assertok(!parts_info);
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ret = ffa_ops->partition_info_get(ffa_dev, service_uuid, &count, parts_info);
+	if (ret != 0) {
+		free(parts_info);
+		ut_assertok(ret != 0);
+	}
+
+	/* SPs found , verify the partitions information */
+
+	ret = CMD_RET_FAILURE;
+
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		for (exp_info_idx = 0;
+		     exp_info_idx < sdx_priv->partitions.count;
+		     exp_info_idx++) {
+			if (parts_info[info_idx].id ==
+			   sdx_priv->partitions.descs[exp_info_idx].info.id) {
+				ret = memcmp(&parts_info[info_idx],
+					     &sdx_priv->partitions.descs[exp_info_idx]
+					     .info,
+					     sizeof(struct ffa_partition_info));
+				if (ret)
+					free(parts_info);
+				ut_assertok(ret != 0);
+				/* Send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
+			}
+			ret = 0;
+		}
+	}
+
+	free(parts_info);
+
+	/* Verify expected partitions found in the emulated secure world */
+	ut_assertok(ret != 0);
+
+	return 0;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_priv *priv = NULL;
+	struct sandbox_ffa_priv *sdx_priv = NULL;
+	struct ffa_sandbox_data func_data = {0};
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	int ret;
+	struct udevice *ffa_dev = NULL, *sdx_dev = NULL;
+	struct ffa_bus_ops *ffa_ops = NULL;
+
+	/* Test probing the FF-A sandbox driver, then binding the FF-A bus driver */
+	uclass_get_device_by_name(UCLASS_FFA, "sandbox_arm_ffa", &sdx_dev);
+	ut_assertok(!sdx_dev);
+
+	/* Test probing the FF-A bus driver */
+	uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev);
+	ut_assertok(!ffa_dev);
+
+	ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev);
+	ut_assertok(!ffa_ops);
+
+	/* Get a pointer to the FF-A core and sandbox drivers private data */
+	priv = dev_get_priv(ffa_dev);
+	sdx_priv = dev_get_priv(sdx_dev);
+
+	/* Make sure private data pointers are retrieved */
+	ut_assertok(priv == 0);
+	ut_assertok(sdx_priv == 0);
+
+	/* Test FFA_VERSION */
+	ut_assertok(check_fwk_version(priv, sdx_priv, uts));
+
+	/* Test FFA_ID_GET */
+	ut_assertok(check_endpoint_id(priv, uts));
+
+	/* Test FFA_FEATURES */
+	ut_assertok(check_features(priv, uts));
+
+	/*  Test core RX/TX buffers */
+	ut_assertok(check_rxtxbuf(priv, uts));
+
+	/* Test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	ut_assertok(sandbox_ffa_query_core_state(sdx_dev, FFA_RXTX_MAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc1_uuid, sdx_priv, uts);
+	ut_assertok(ret != 0);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(sdx_dev, FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc2_uuid, sdx_priv, uts);
+	ut_assertok(ret != 0);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(sdx_dev, FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* Test FFA_RXTX_UNMAP */
+	ut_assertok(ffa_ops->rxtx_unmap(ffa_dev));
+
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(sdx_dev, FFA_RXTX_UNMAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts));
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_priv *priv = NULL;
+	struct sandbox_ffa_priv *sdx_priv = NULL;
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	u32 count = 0;
+	u16 part_id = 0;
+	struct udevice *ffa_dev = NULL, *sdx_dev = NULL;
+	struct ffa_bus_ops *ffa_ops = NULL;
+
+	/* Test probing the FF-A sandbox driver, then binding the FF-A bus driver */
+	uclass_get_device_by_name(UCLASS_FFA, "sandbox_arm_ffa", &sdx_dev);
+	ut_assertok(!sdx_dev);
+
+	/* Test probing the  FF-A bus driver */
+	uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev);
+	ut_assertok(!ffa_dev);
+
+	ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev);
+	ut_assertok(!ffa_ops);
+
+	/* Get a pointer to the FF-A core and sandbox drivers private data */
+	priv = dev_get_priv(ffa_dev);
+	sdx_priv = dev_get_priv(sdx_dev);
+
+	/* Make sure private data pointers are retrieved */
+	ut_assertok(priv == 0);
+	ut_assertok(sdx_priv == 0);
+
+	/* Query partitions count using  invalid arguments */
+	ret = ffa_ops->partition_info_get(ffa_dev, unvalid_svc_uuid, NULL, NULL);
+	ut_assertok(ret != -EINVAL);
+
+	/* Query partitions count using an invalid UUID  string */
+	ret = ffa_ops->partition_info_get(ffa_dev, unvalid_svc_uuid_str, &count, NULL);
+	ut_assertok(ret != -EINVAL);
+
+	/* Query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_ops->partition_info_get(ffa_dev, unvalid_svc_uuid, &count, NULL);
+	ut_assertok(count != 0);
+
+	/* Query partitions count using a valid UUID */
+	count = 0;
+	ret = ffa_ops->partition_info_get(ffa_dev, valid_svc_uuid, &count, NULL);
+	/* Make sure partitions are detected */
+	ut_assertok(ret != 0);
+	ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
+
+	/* Send data to an invalid partition */
+	ret = ffa_ops->sync_send_receive(ffa_dev, part_id, &msg, 1);
+	ut_assertok(ret != -EINVAL);
+
+	/* Send data to a valid partition */
+	part_id = priv->partitions.descs[0].info.id;
+	ret = ffa_ops->sync_send_receive(ffa_dev, part_id, &msg, 1);
+	ut_assertok(ret != 0);
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v9 08/10] arm_ffa: introduce armffa command Sandbox test
  2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                       ` (6 preceding siblings ...)
  2023-03-10 14:10                                                                                     ` [PATCH v9 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-03-10 14:10                                                                                     ` Abdellatif El Khlifi
  2023-03-10 20:50                                                                                       ` Simon Glass
  2023-03-10 14:10                                                                                     ` [PATCH v9 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
                                                                                                       ` (2 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-10 14:10 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

Add Sandbox test for the armffa command

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>

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

v9: align the test with FF-A discovery through DM

v4: drop use of helper APIs

v1: introduce armffa command sandbox test

 MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 39 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 6939b832e4..b36fb41668 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -275,6 +275,7 @@ F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/sandbox_arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 2ffde8703a..e74da56a29 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -19,6 +20,7 @@ obj-$(CONFIG_CMD_PWM) += pwm.o
 obj-$(CONFIG_CMD_SEAMA) += seama.o
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_SANDBOX_FFA) += armffa.o
 endif
 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
 obj-$(CONFIG_CMD_WGET) += wget.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..73c895f182
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * 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 <sandbox_arm_ffa.h>
+#include <string.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define PING_CMD_SIZE 19
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	char ping_cmd[PING_CMD_SIZE] = {0};
+
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	snprintf(ping_cmd, PING_CMD_SIZE, "armffa ping 0x%x", SANDBOX_SP1_ID);
+
+	/* armffa ping <ID> */
+	ut_assertok(run_command(ping_cmd, 0));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return CMD_RET_SUCCESS;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v9 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                       ` (7 preceding siblings ...)
  2023-03-10 14:10                                                                                     ` [PATCH v9 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2023-03-10 14:10                                                                                     ` Abdellatif El Khlifi
  2023-03-10 20:50                                                                                       ` Simon Glass
  2023-03-10 14:10                                                                                     ` [PATCH v9 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  2023-03-10 20:50                                                                                     ` [PATCH v9 00/10] introduce Arm FF-A support Simon Glass
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-10 14:10 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong, Gowtham Suresh Kumar

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

MM communication protocol supports FF-A 64-bit direct messaging.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>

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

v9: align how FF-A is used with FF-A discovery through DM

v8:

* isolate the compilation choices between FF-A and OP-TEE
* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make mm_sp_svc_uuid static
* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
* improve use of unmap_sysmem() in ffa_mm_communicate()

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

 include/mm_communication.h        |   6 +
 lib/efi_loader/Kconfig            |  14 +-
 lib/efi_loader/efi_variable_tee.c | 317 +++++++++++++++++++++++++++++-
 3 files changed, 331 insertions(+), 6 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..87509fec3f 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,9 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *    Authors:
+ *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +16,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c5835e6ef6..08a6b84101 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	depends on OPTEE || ARM_FFA_TRANSPORT
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..86207f1ff2 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,9 +4,14 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  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 <efi.h>
 #include <efi_api.h>
 #include <efi_loader.h>
@@ -15,6 +20,36 @@
 #include <malloc.h>
 #include <mm_communication.h>
 
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+#include <arm_ffa.h>
+#include <cpu_func.h>
+#include <mapmem.h>
+
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_SIZE 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_OFFSET
+#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_OFFSET 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_ADDR 0
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+
+static const char *mm_sp_svc_uuid = MM_SP_UUID;
+
+static u16 mm_sp_id;
+
+#endif
+
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -24,6 +59,7 @@ struct mm_connection {
 	u32 session;
 };
 
+#if (IS_ENABLED(CONFIG_OPTEE))
 /**
  * get_connection() - Retrieve OP-TEE session for a specific UUID.
  *
@@ -143,13 +179,269 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 
 	return ret;
 }
+#endif
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+/**
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notifies the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret = -1;
+	struct udevice *ffa_dev = NULL;
+	struct ffa_bus_ops *ffa_ops = NULL;
+
+	uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev);
+	if (!ffa_dev) {
+		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
+		return -ENODEV;
+	}
+
+	ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev);
+	if (!ffa_ops) {
+		log_err("EFI: Invalid FF-A ops, notify MM SP failure\n");
+		return -EINVAL;
+	}
+
+	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
+
+	ret = ffa_ops->sync_send_receive(ffa_dev, mm_sp_id, &msg, 1);
+	if (ret != 0)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	if (sp_event_ret == MM_SUCCESS)
+		return 0;
+
+	/*
+	 * Failure to notify the MM SP
+	 */
+
+	return -EACCES;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+	struct udevice *ffa_dev = NULL;
+	struct ffa_bus_ops *ffa_ops = NULL;
+
+	uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev);
+	if (!ffa_dev) {
+		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
+		return -ENODEV;
+	}
+
+	ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev);
+	if (!ffa_ops) {
+		log_err("EFI: Invalid FF-A ops, MM SP discovery failure\n");
+		return -EINVAL;
+	}
+
+	/* Get from the driver the count of the SPs matching the UUID */
+	ret = ffa_ops->partition_info_get(ffa_dev, mm_sp_svc_uuid, &count, NULL);
+	if (ret != 0) {
+		log_err("EFI: Failure in querying SPs count (%d), MM SP discovery failure\n", ret);
+		return ret;
+	}
+
+	if (!count) {
+		log_info("EFI: No MM partition found\n");
+		return ret;
+	}
+
+	/* Pre-allocate a buffer to be filled by the driver with ffa_partition_info structs */
+
+	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
+
+	parts_info = calloc(count, sizeof(*parts_info));
+	if (!parts_info)
+		return -ENOMEM;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ret = ffa_ops->partition_info_get(ffa_dev, mm_sp_svc_uuid, &count, parts_info);
+	if (ret) {
+		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/* MM SPs found , use the first one */
+
+	mm_sp_id = parts_info[0].id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	efi_status_t efi_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
+		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+	#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+	#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+
+	switch (ffa_ret) {
+	case 0:
+	{
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		efi_ret = EFI_SUCCESS;
+		break;
+	}
+	case -EINVAL:
+		efi_ret = EFI_DEVICE_ERROR;
+		break;
+	case -EPERM:
+		efi_ret = EFI_INVALID_PARAMETER;
+		break;
+	case -EACCES:
+		efi_ret = EFI_ACCESS_DENIED;
+		break;
+	case -EBUSY:
+		efi_ret = EFI_OUT_OF_RESOURCES;
+		break;
+	default:
+		efi_ret = EFI_ACCESS_DENIED;
+	}
+
+	unmap_sysmem(virt_shared_buf);
+	return efi_ret;
+}
+#endif
+
+/**
+ * select_ffa_mm_comms() - checks FF-A support availability
+ *
+ * Making sure FF-A is compiled in. If that's the case try to make sure
+ * the FF-A bus is probed successfully which means FF-A communication
+ * with secure world works and ready to be used.
+ *
+ * Return:
+ *
+ * 0: FF-A ready for use. Otherwise, failure
+ */
+static efi_status_t select_ffa_mm_comms(void)
+{
+	efi_status_t ret = EFI_UNSUPPORTED;
+
+	if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) {
+		struct udevice *dev = NULL;
+
+		uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &dev);
+		if (!dev) {
+			log_err("EFI: Cannot find FF-A bus device, cannot select FF-A comms\n");
+			ret = EFI_NOT_READY;
+		} else {
+			ret = EFI_SUCCESS;
+		}
+	}
+
+	return ret;
+}
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
@@ -162,7 +454,17 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+	ret = select_ffa_mm_comms();
+	if (ret != EFI_SUCCESS) {
+#if (IS_ENABLED(CONFIG_OPTEE))
+		ret = optee_mm_communicate(comm_buf, dsize);
+#endif
+	} else {
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+		ret = ffa_mm_communicate(comm_buf, dsize);
+#endif
+	}
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -258,6 +560,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
 		goto out;
 	}
 	*size = var_payload->size;
+
+	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
+			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
+				MM_VARIABLE_COMMUNICATE_SIZE;
+	#endif
+
 	/*
 	 * There seems to be a bug in EDK2 miscalculating the boundaries and
 	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
@@ -697,7 +1006,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v9 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                       ` (8 preceding siblings ...)
  2023-03-10 14:10                                                                                     ` [PATCH v9 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-03-10 14:10                                                                                     ` Abdellatif El Khlifi
  2023-03-10 20:50                                                                                     ` [PATCH v9 00/10] introduce Arm FF-A support Simon Glass
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-10 14:10 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

turn on EFI MM communication

On corstone1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

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>

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

v9: update copyright string

v8:

* drop OP-TEE configs from Corstone-1000 defconfig

v7:

* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
  FFA_SHARED_MM_BUFFER_OFFSET
* update FFA_SHARED_MM_BUFFER_ADDR value

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

 configs/corstone1000_defconfig |  2 ++
 include/configs/corstone1000.h | 15 +++++++++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index 74250c7524..a7bfcbb2b9 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -52,3 +52,5 @@ CONFIG_DM_SERIAL=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760=y
 CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
index 3347c11792..4ef1f05e40 100644
--- a/include/configs/corstone1000.h
+++ b/include/configs/corstone1000.h
@@ -1,9 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * (C) Copyright 2022 ARM Limited
  * (C) Copyright 2022 Linaro
  * Rui Miguel Silva <rui.silva@linaro.org>
- * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  *
  * Configuration for Corstone1000. Parts were derived from other ARM
  * configurations.
@@ -14,6 +16,15 @@
 
 #include <linux/sizes.h>
 
+#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
+
+/*
+ * shared buffer physical address used for communication between
+ * u-boot and the MM SP
+ */
+#define FFA_SHARED_MM_BUFFER_ADDR	0x02000000UL
+#define FFA_SHARED_MM_BUFFER_OFFSET	0
+
 #define V2M_BASE		0x80000000
 
 #define CFG_PL011_CLOCK	50000000
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v9 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2023-03-10 14:10                                                                                     ` [PATCH v9 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2023-03-10 20:49                                                                                       ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-03-10 20:49 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sudeep.holla, trini, u-boot, xueliang.zhong

On Fri, 10 Mar 2023 at 06:10, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> convert UUID string to little endian binary data
>
> 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>
>
> ---
> Changelog:
> ===============
>
> v9:
>
> * add a full function prototype description in uuid.h
>
> v8:
>
> * use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms
>
> v7:
>
> * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> * make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
>   by using same APIs
>
> v4:
>
> * rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
>   a standalone commit (the current)
>
> v3:
>
> * introduce ffa_uuid_str_to_bin (provided by
>   arm_ffa: introduce Arm FF-A low-level driver)
>
>  include/uuid.h | 15 +++++++++++++++
>  lib/uuid.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 63 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v9 05/10] arm_ffa: introduce armffa command
  2023-03-10 14:10                                                                                     ` [PATCH v9 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-03-10 20:49                                                                                       ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-03-10 20:49 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sudeep.holla, trini, u-boot, xueliang.zhong

Hi Abdellatif,

On Fri, 10 Mar 2023 at 06:10, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Provide armffa command showcasing the use of the FF-A driver
>
> armffa is a command showcasing how to use the FF-A driver and how to invoke
> its operations. This provides a guidance to the client developers on how to
> call the FF-A bus interfaces. The command also allows to gather secure
> partitions information and ping these  partitions. The command is also
> helpful in testing the communication with secure partitions.
>
> For more details please refer to the command documentation [1].
>
> [1]: doc/usage/cmd/armffa.rst
>
> 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>
>
> ---
> Changelog:
> ===============
>
> v9:
>
> * remove manual FF-A discovery and use DM
> * use DM class APIs to probe and interact with the FF-A bus
> * add doc/usage/cmd/armffa.rst
>
> v8:
>
> * update partition_info_get() second argument to be an SP count
> * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7:
>
> * adapt do_ffa_dev_list() following the recent update on
>   uclass_first_device/uclass_next_device functions (they return void now)
> * set armffa command to use 64-bit direct messaging
>
> v4:
>
> * remove pattern data in do_ffa_msg_send_direct_req
>
> v3:
>
> * use the new driver interfaces (partition_info_get, sync_send_receive)
>   in armffa command
>
> v2:
>
> * replace use of ffa_helper_init_device function by
>  ffa_helper_bus_discover
>
> v1:
>
> * introduce armffa command
>
>  MAINTAINERS                      |   2 +
>  cmd/Kconfig                      |  10 ++
>  cmd/Makefile                     |   2 +
>  cmd/armffa.c                     | 264 +++++++++++++++++++++++++++++++
>  doc/usage/cmd/armffa.rst         | 118 ++++++++++++++
>  doc/usage/index.rst              |   1 +

+Heinrich Schuchardt for docs

>  drivers/firmware/arm-ffa/Kconfig |   1 +
>  7 files changed, 398 insertions(+)
>  create mode 100644 cmd/armffa.c
>  create mode 100644 doc/usage/cmd/armffa.rst
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1dfa23c1f0..18e9c2ce99 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -269,7 +269,9 @@ F:  configs/cortina_presidio-asic-pnand_defconfig
>  ARM FF-A
>  M:     Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>  S:     Maintained
> +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
>
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index a3512836c1..f24c52def4 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -934,6 +934,16 @@ endmenu
>
>  menu "Device access commands"
>
> +config CMD_ARMFFA
> +       bool "Arm FF-A test command"
> +       depends on ARM_FFA_TRANSPORT
> +       help
> +         Provides a test command for the Arm FF-A driver
> +         supported options:
> +               - Listing the partition(s) info
> +               - Sending a data pattern to the specified partition
> +               - Displaying the arm_ffa device info
> +
>  config CMD_ARMFLASH
>         #depends on FLASH_CFI_DRIVER
>         bool "armflash"
> diff --git a/cmd/Makefile b/cmd/Makefile
> index 2d8bb4fc05..a59ab55ad0 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -12,6 +12,8 @@ obj-y += panic.o
>  obj-y += version.o
>
>  # command
> +
> +obj-$(CONFIG_CMD_ARMFFA) += armffa.o
>  obj-$(CONFIG_CMD_ACPI) += acpi.o
>  obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
>  obj-$(CONFIG_CMD_AES) += aes.o
> diff --git a/cmd/armffa.c b/cmd/armffa.c
> new file mode 100644
> index 0000000000..f6c017542d
> --- /dev/null
> +++ b/cmd/armffa.c
> @@ -0,0 +1,264 @@
> +// 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 <command.h>
> +#include <dm.h>
> +#include <mapmem.h>
> +#include <stdlib.h>
> +#include <asm/io.h>
> +
> +/**
> + * do_ffa_getpart() - implementation of the getpart subcommand
> + * @cmdtp:             Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * This function queries the secure partition information which the UUID is provided
> + * as an argument. The function uses the arm_ffa driver partition_info_get operation
> + * which implements FFA_PARTITION_INFO_GET ABI to retrieve the data.
> + * The input UUID string is expected to be in big endian format.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       u32 count = 0;
> +       int ret;
> +       struct ffa_partition_info *parts_info;
> +       u32 info_idx;
> +       struct udevice *dev = NULL;
> +       struct ffa_bus_ops *ffa_ops = NULL;
> +
> +       if (argc != 1)
> +               return -EINVAL;
> +
> +       uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &dev);

uclass_first_device()

The name is most likely to have a hyphen than an underscore due to
devicetree conventions. Anyway, there should be only one.

> +       if (!dev) {
> +               log_err("[FFA] Cannot find FF-A bus device\n");
> +               return -ENODEV;
> +       }
> +
> +       ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(dev);unl
> +       if (!ffa_ops) {
> +               log_err("[FFA] Invalid FF-A ops\n");
> +               return -EINVAL;
> +       }
> +
> +       /* Mode 1: getting the number of secure partitions */
> +       ret = ffa_ops->partition_info_get(dev, argv[0], &count, NULL);

These should be uclass operations in armffa.h, i.e. they implement the
uclass. See how other things do this, e.g. p2sb.h is a really simple
example. Then you implement the callers in armffa-uclass.c rather than
accessing the ops here.

> +       if (ret != 0) {

if (ret)

Please fix below

> +               log_err("[FFA] Failure in querying partitions count (error code: %d)\n", ret);
> +               return ret;
> +       }
> +
> +       if (!count) {
> +               log_info("[FFA] No secure partition found\n");
> +               return ret;
> +       }
> +
> +       /*
> +        * Pre-allocate a buffer to be filled by the driver
> +        * with ffa_partition_info structs
> +        */
> +
> +       log_info("[FFA] Pre-allocating %d partition(s) info structures\n", count);
> +
> +       parts_info = calloc(count, sizeof(struct ffa_partition_info));
> +       if (!parts_info)
> +               return -EINVAL;
> +
> +       /* Ask the driver to fill the buffer with the SPs info */
> +
> +       ret = ffa_ops->partition_info_get(dev, argv[0], &count, parts_info);

here again the operation

> +       if (ret != 0) {
> +               log_err("[FFA] Failure in querying partition(s) info (error code: %d)\n", ret);
> +               free(parts_info);
> +               return ret;
> +       }
> +
> +       /* SPs found , show the partition information */
> +       for (info_idx = 0; info_idx < count ; info_idx++) {
> +               log_info("[FFA] Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x\n",
> +                        parts_info[info_idx].id,
> +                        parts_info[info_idx].exec_ctxt,
> +                        parts_info[info_idx].properties);
> +       }
> +
> +       free(parts_info);
> +
> +       return 0;
> +}
> +
> +/**
> + * do_ffa_ping() - implementation of the ping subcommand
> + * @cmdtp:             Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * This function sends data to the secure partition which the ID is provided
> + * as an argument. The function uses the arm_ffa driver sync_send_receive operation
> + * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       struct ffa_send_direct_data msg = {
> +                       .data0 = 0xaaaaaaaa,
> +                       .data1 = 0xbbbbbbbb,
> +                       .data2 = 0xcccccccc,
> +                       .data3 = 0xdddddddd,
> +                       .data4 = 0xeeeeeeee,
> +       };
> +       u16 part_id;
> +       int ret;
> +       struct udevice *dev = NULL;
> +       struct ffa_bus_ops *ffa_ops = NULL;
> +
> +       if (argc != 1)
> +               return -EINVAL;
> +
> +       errno = 0;
> +       part_id = strtoul(argv[0], NULL, 16);
> +
> +       if (errno) {
> +               log_err("[FFA] Invalid partition ID\n");
> +               return -EINVAL;
> +       }
> +
> +       uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &dev);
> +       if (!dev) {
> +               log_err("[FFA] Cannot find FF-A bus device\n");
> +               return -ENODEV;
> +       }
> +
> +       ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(dev);
> +       if (!ffa_ops) {
> +               log_err("[FFA] Invalid FF-A ops\n");
> +               return -EINVAL;
> +       }
> +
> +       ret = ffa_ops->sync_send_receive(dev, part_id, &msg, 1);
> +       if (!ret) {
> +               u8 cnt;
> +
> +               log_info("[FFA] SP response:\n[LSB]\n");
> +               for (cnt = 0;
> +                    cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
> +                    cnt++)
> +                       log_info("[FFA] 0x%llx\n", ((u64 *)&msg)[cnt]);
> +       } else {
> +               log_err("[FFA] Sending direct request error (%d)\n", ret);
> +       }
> +
> +       return ret;
> +}
> +
> +/**
> + *do_ffa_devlist() - implementation of the devlist subcommand
> + * @cmdtp: [in]                Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * This function queries the devices belonging to the UCLASS_FFA
> + * class.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       struct udevice *dev = NULL;
> +       int i;
> +
> +       log_info("[FFA] FF-A uclass entries:\n");
> +
> +       for (i = 0, uclass_first_device(UCLASS_FFA, &dev);
> +            dev;
> +            uclass_next_device(&dev), i++) {

uclass_foreacah_dev_probe(dUCLASS_FFA, dev) {

> +               log_info("[FFA] entry %d - instance %08x, ops %08x, plat %08x\n",
> +                        i,
> +                        (u32)map_to_sysmem(dev),
> +                        (u32)map_to_sysmem(dev->driver->ops),
> +                        (u32)map_to_sysmem(dev_get_plat(dev)));
> +       }
> +
> +       return 0;
> +}
> +
> +static struct cmd_tbl armffa_commands[] = {
> +       U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_getpart, "", ""),
> +       U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_ping, "", ""),
> +       U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_devlist, "", ""),
> +};
> +
> +/**
> + * do_armffa() - the armffa command main function
> + * @cmdtp:     Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * This function identifies which armffa subcommand to run.
> + * Then, it makes sure the arm_ffa device is probed and
> + * ready for use.
> + * Then, it runs the subcommand.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       struct cmd_tbl *armffa_cmd;
> +       int ret;
> +
> +       if (argc < 2)
> +               return CMD_RET_USAGE;
> +
> +       armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
> +
> +       argc -= 2;
> +       argv += 2;
> +
> +       if (!armffa_cmd || argc > armffa_cmd->maxargs)
> +               return CMD_RET_USAGE;
> +
> +       if (IS_ENABLED(CONFIG_SANDBOX_FFA)) {

No, this needs to be bound automatically. Add it to test.dts and let
sandbox bind it.

> +               struct udevice *sdx_dev = NULL;
> +               /*  Probe the FF-A sandbox driver, then bind the FF-A bus driver */
> +               uclass_get_device_by_name(UCLASS_FFA, "sandbox_arm_ffa", &sdx_dev);
> +               if (!sdx_dev) {
> +                       log_err("[FFA] Cannot find FF-A sandbox device\n");
> +                       return -ENODEV;
> +               }
> +       }
> +
> +       ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
> +
> +       return cmd_process_error(armffa_cmd, ret);
> +}

[..]

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v9 06/10] arm_ffa: introduce the FF-A Sandbox driver
  2023-03-10 14:10                                                                                     ` [PATCH v9 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
@ 2023-03-10 20:49                                                                                       ` Simon Glass
  2023-03-14 12:55                                                                                         ` Abdellatif El Khlifi
  2023-03-14 17:59                                                                                         ` Abdellatif El Khlifi
  0 siblings, 2 replies; 478+ messages in thread
From: Simon Glass @ 2023-03-10 20:49 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sudeep.holla, trini, u-boot, xueliang.zhong

Hi Abdellatif,

On Fri, 10 Mar 2023 at 06:10, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> 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>
>
> ---
> Changelog:
> ===============
>
> v9: align FF-A sandbox driver with FF-A discovery through DM
>
> v8: update ffa_bus_prvdata_get() to return a pointer rather than
>     a pointer address
>
> v7: state that sandbox driver supports only 64-bit direct messaging
>
> v4: align sandbox driver with the new FF-A driver interfaces
>     and new way of error handling
>
> v1: introduce the sandbox driver
>
>  MAINTAINERS                                   |   1 +
>  arch/sandbox/dts/sandbox.dtsi                 |   4 +
>  arch/sandbox/dts/test.dts                     |   4 +
>  configs/sandbox64_defconfig                   |   2 +
>  configs/sandbox_defconfig                     |   2 +
>  doc/arch/arm64.ffa.rst                        |   4 +
>  doc/arch/sandbox/sandbox.rst                  |   1 +
>  drivers/firmware/arm-ffa/Kconfig              |  11 +-
>  drivers/firmware/arm-ffa/Makefile             |   1 +
>  drivers/firmware/arm-ffa/core.c               |  36 +-
>  drivers/firmware/arm-ffa/sandbox.c            | 610 ++++++++++++++++++
>  .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   | 129 ++++
>  include/arm_ffa.h                             |   5 +-
>  include/sandbox_arm_ffa.h                     | 124 ++++
>  14 files changed, 928 insertions(+), 6 deletions(-)
>  create mode 100644 drivers/firmware/arm-ffa/sandbox.c
>  create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
>  create mode 100644 include/sandbox_arm_ffa.h
>

Could you use 80 columns where possible? There seem to be a lot of
things that extend beyond that without much of a reason.

Also you can use 'ulong' instead of 'unsigned long'. It is less
verbose and a U-Boot standard.

> diff --git a/MAINTAINERS b/MAINTAINERS
> index 18e9c2ce99..2b9d33e964 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -274,6 +274,7 @@ 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..059c273277 100644
> --- a/arch/sandbox/dts/sandbox.dtsi
> +++ b/arch/sandbox/dts/sandbox.dtsi
> @@ -445,6 +445,10 @@
>         thermal {
>                 compatible = "sandbox,thermal";
>         };
> +
> +       sandbox_arm_ffa {
> +               compatible = "sandbox,arm_ffa";
> +       };
>  };
>
>  &cros_ec {
> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index d72d7a567a..11dc6ed0d9 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -1802,6 +1802,10 @@
>                 compatible = "u-boot,fwu-mdata-gpt";
>                 fwu-mdata-store = <&mmc0>;
>         };
> +
> +       sandbox_arm_ffa {
> +               compatible = "sandbox,arm_ffa";
> +       };

I see that you have this, so the driver should bind automatically.

Is the problem that you are trying to bind the sandbox emulator?
Again, you can actually add that to the DT. See how this works for
i2c, SPI, PCI, for example.

>  };
>
>  #include "sandbox_pmic.dtsi"
> diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
> index ccbc18aad0..35d4676cf7 100644
> --- a/configs/sandbox64_defconfig
> +++ b/configs/sandbox64_defconfig
> @@ -259,3 +259,5 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
>  CONFIG_UNIT_TEST=y
>  CONFIG_UT_TIME=y
>  CONFIG_UT_DM=y
> +CONFIG_ARM_FFA_TRANSPORT=y
> +CONFIG_SANDBOX_FFA=y
> diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
> index a0fbdad20a..8aab8dda31 100644
> --- a/configs/sandbox_defconfig
> +++ b/configs/sandbox_defconfig
> @@ -336,3 +336,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/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> index 8fad9ef3d0..555ee9a6ae 100644
> --- a/doc/arch/arm64.ffa.rst
> +++ b/doc/arch/arm64.ffa.rst
> @@ -64,6 +64,10 @@ CONFIG_ARM_FFA_TRANSPORT
>      Enables the FF-A bus driver. Turn this on if you want to use FF-A
>      communication.
>
> +CONFIG_SANDBOX_FFA
> +    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
> +    Sandbox and provides functional tests for FF-A.

OK that is why I am confused. Please don't call this a driver. It is
an emulator. When you have an emulator and a driver for the same thing
it gets confusing.

> +
>  FF-A ABIs under the hood
>  ---------------------------------------
>
> diff --git a/doc/arch/sandbox/sandbox.rst b/doc/arch/sandbox/sandbox.rst
> index cd7f8a2cb0..c5df372e00 100644
> --- a/doc/arch/sandbox/sandbox.rst
> +++ b/doc/arch/sandbox/sandbox.rst
> @@ -200,6 +200,7 @@ Supported Drivers
>
>  U-Boot sandbox supports these emulations:
>
> +- Arm FF-A
>  - Block devices
>  - Chrome OS EC
>  - GPIO
> diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> index 2cfd7ef5fc..b5430eb6f4 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
> @@ -32,3 +32,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 c8d83b4bc9..d22c1ba609 100644
> --- a/drivers/firmware/arm-ffa/Makefile
> +++ b/drivers/firmware/arm-ffa/Makefile
> @@ -6,3 +6,4 @@
>  #   Abdellatif El Khlifi <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/core.c b/drivers/firmware/arm-ffa/core.c
> index 2210f5343c..0d2e6ff0d4 100644
> --- a/drivers/firmware/arm-ffa/core.c
> +++ b/drivers/firmware/arm-ffa/core.c
> @@ -1042,6 +1042,7 @@ bool ffa_try_discovery(void)
>         return true;
>  }
>
> +#if !CONFIG_IS_ENABLED(SANDBOX_FFA)

We should not need #ifdefs here. The sandbox driver is just another
driver, just like there is the ARM driver. We select the correct one
using the devicetree and everything just works.

>  /**
>   * __arm_ffa_fn_smc() - SMC wrapper
>   * @args: FF-A ABI arguments to be copied to Xn registers
> @@ -1069,6 +1070,7 @@ void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
>   * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
>   * So, the legacy SMC invocation is not used.
>   *
> + * In Sandbox mode sandbox_arm_ffa is used to test arm_ffa driver.
>   * Return:
>   *
>   * 0 on success. Otherwise, failure
> @@ -1088,6 +1090,30 @@ ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
>         .driver_name = FFA_DRV_NAME,
>         .is_supported = ffa_bus_is_supported,
>  };
> +#else
> +/* SANDBOX_FFA */
> +
> +/**
> + * ffa_bind() - The driver bind function
> + * @dev:       the arm_ffa device
> + * When using sandbox tries to discover the emulated FF-A bus.
> + * Return:
> + *
> + * 0 on success.
> + */
> +static int ffa_bind(struct udevice *dev)

I don't think this is binding anything. How about ffa_get_dev() ?

> +{
> +       bool ret;
> +
> +       log_info("[FFA] binding the device\n");
> +
> +       ret = ffa_try_discovery();
> +       if (ret)
> +               return 0;
> +       else
> +               return -ENODEV;
> +}
> +#endif
>
>  /**
>   * ffa_set_smc_conduit() - Set the SMC conduit
> @@ -1101,7 +1127,12 @@ ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
>   */
>  static int ffa_set_smc_conduit(void)
>  {
> -       dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc;
> +#if CONFIG_IS_ENABLED(SANDBOX_FFA)
> +               dscvry_info.invoke_ffa_fn = sandbox_arm_ffa_smccc_smc;
> +               log_info("[FFA] Using SMC emulation\n");
> +#else
> +               dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc;
> +#endif

This needs to be reworked to go through the uclass to the correct
driver. Basically you need an ARM driver and a sandbox driver (which
attaches to the emulator).

There should not be #idefs in this sort of code...driver model should
handle it. See other uclasses for examples.

>
>         log_info("[FFA] Conduit is SMC\n");
>
> @@ -1246,4 +1277,7 @@ U_BOOT_DRIVER(arm_ffa) = {
>         .remove = ffa_remove,
>         .unbind = ffa_unbind,
>         .ops            = &ffa_ops,
> +#if CONFIG_IS_ENABLED(SANDBOX_FFA)
> +       .bind           = ffa_bind,

Can drop this

> +#endif
>  };
> diff --git a/drivers/firmware/arm-ffa/sandbox.c b/drivers/firmware/arm-ffa/sandbox.c

sandbox_emul.c pehaps?

I am pretty sure this is an emulator

> new file mode 100644
> index 0000000000..84c2fc929f
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/sandbox.c
> @@ -0,0 +1,610 @@
> +// 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 <dm/device-internal.h>
> +#include <dm/lists.h>
> +#include <dm/root.h>
> +#include <linux/errno.h>
> +#include <linux/sizes.h>
> +#include "sandbox_arm_ffa_priv.h"
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* The partitions (SPs) table */
> +static struct ffa_partition_desc sandbox_partitions[SANDBOX_PARTITIONS_CNT] = {
> +       {
> +               .info = { .id = SANDBOX_SP1_ID, .exec_ctxt = 0x5687, .properties = 0x89325621 },
> +               .sp_uuid = {
> +                       .a1 = SANDBOX_SERVICE1_UUID_A1,
> +                       .a2 = SANDBOX_SERVICE1_UUID_A2,
> +                       .a3 = SANDBOX_SERVICE1_UUID_A3,
> +                       .a4 = SANDBOX_SERVICE1_UUID_A4,
> +               }
> +       },
> +       {
> +               .info = { .id = SANDBOX_SP2_ID, .exec_ctxt = 0x9587, .properties = 0x45325621 },
> +               .sp_uuid = {
> +                       .a1 = SANDBOX_SERVICE2_UUID_A1,
> +                       .a2 = SANDBOX_SERVICE2_UUID_A2,
> +                       .a3 = SANDBOX_SERVICE2_UUID_A3,
> +                       .a4 = SANDBOX_SERVICE2_UUID_A4,
> +               }
> +       },
> +       {
> +               .info = { .id = SANDBOX_SP3_ID, .exec_ctxt = 0x7687, .properties = 0x23325621 },
> +               .sp_uuid = {
> +                       .a1 = SANDBOX_SERVICE1_UUID_A1,
> +                       .a2 = SANDBOX_SERVICE1_UUID_A2,
> +                       .a3 = SANDBOX_SERVICE1_UUID_A3,
> +                       .a4 = SANDBOX_SERVICE1_UUID_A4,
> +               }
> +       },
> +       {
> +               .info = { .id = SANDBOX_SP4_ID, .exec_ctxt = 0x1487, .properties = 0x70325621 },
> +               .sp_uuid = {
> +                       .a1 = SANDBOX_SERVICE2_UUID_A1,
> +                       .a2 = SANDBOX_SERVICE2_UUID_A2,
> +                       .a3 = SANDBOX_SERVICE2_UUID_A3,
> +                       .a4 = SANDBOX_SERVICE2_UUID_A4,
> +               }
> +       }
> +
> +};
> +
> +/* Driver functions */
> +
> +/**
> + * sandbox_ffa_version() - Emulated FFA_VERSION handler function
> + * @dev:       the sandbox FF-A device
> + * @{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)

Instead of the macro can you write this out in full? It defeats ctags, etc.

> +{
> +       struct sandbox_ffa_priv *priv = dev_get_priv(dev);
> +
> +       priv->fwk_version = FFA_VERSION_1_0;
> +       res->a0 = priv->fwk_version;

Where is res defined?

> +
> +       /* 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
> + * @dev:       the sandbox FF-A device
> + * @{a0-a7} , res: The SMC call arguments and return structure.
> + *
> + * This is the function that emulates FFA_ID_GET FF-A function.

s/This is the function that e/E/g

> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +SANDBOX_SMC_FFA_ABI(ffa_id_get)
> +{
> +       struct sandbox_ffa_priv *priv = dev_get_priv(dev);
> +
> +       res->a0 = FFA_SMC_32(FFA_SUCCESS);
> +       res->a1 = 0;
> +
> +       priv->id = NS_PHYS_ENDPOINT_ID;
> +       res->a2 = priv->id;
> +
> +       /* x3-x7 MBZ */
> +       memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long));
> +
> +       return 0;
> +}
> +
> +/**
> + * sandbox_ffa_features() - Emulated FFA_FEATURES handler function
> + * @dev:       the sandbox FF-A device
> + * @{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));
> +               log_err("[FFA] [Sandbox] FF-A interface 0x%lx not implemented\n", pargs->a1);

return -ENOSYS

> +       }
> +
> +       res->a1 = 0;
> +
> +       return 0;
> +}
> +

[..]

> +SANDBOX_SMC_FFA_ABI(ffa_msg_send_direct_req)
> +{
> +       u16 part_id;
> +       struct sandbox_ffa_priv *priv = dev_get_priv(dev);
> +
> +       part_id = GET_DST_SP_ID(pargs->a1);
> +
> +       if ((GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id) ||

drop extra brackets

> +           !sandbox_ffa_sp_valid(dev, 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(priv->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;

Would -1UL work?

> +
> +       return 0;
> +}
> +

[..]

> +static int sandbox_ffa_probe(struct udevice *dev)
> +{
> +       struct udevice *child_dev = NULL;
> +       int ret;
> +
> +       ret = device_bind_driver(dev, FFA_DRV_NAME, FFA_DRV_NAME, &child_dev);

Is this binding the emulator? Add it to the DT instead.

If you put

.post_bind = dm_scan_fdt_dev()

in your uclass (like spi-uclass.c does) then it will binding
child-node devices automatically. Then you can make your emulator a
child node.

> +       if (ret) {
> +               pr_err("%s was not bound: %d, aborting\n", FFA_DRV_NAME, ret);
> +               return -ENODEV;
> +       }
> +
> +       dev_set_parent_plat(child_dev, dev_get_plat(dev));
> +
> +       return 0;
> +}
> +
> +static const struct udevice_id sandbox_ffa_id[] = {
> +       { "sandbox,arm_ffa", 0 },
> +       { },
> +};
> +
> +/* Declaring the sandbox_arm_ffa driver under UCLASS_FFA */
> +U_BOOT_DRIVER(sandbox_arm_ffa) = {
> +       .name           = FFA_SANDBOX_DRV_NAME,
> +       .of_match = sandbox_ffa_id,
> +       .id             = UCLASS_FFA,
> +       .probe          = sandbox_ffa_probe,
> +       .priv_auto      = sizeof(struct sandbox_ffa_priv),
> +};
> diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> new file mode 100644
> index 0000000000..c35d80de16
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> @@ -0,0 +1,129 @@
> +/* 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 <sandbox_arm_ffa.h>
> +#include "arm_ffa_priv.h"
> +
> +/* This header is exclusively used by the Sandbox FF-A driver and sandbox tests */
> +
> +/* 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

It's a convention to put negative values in brackets just in case of
operator-precedence issues. Or you could use an enum.

> +
> +/* 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 secure partitions emulated by the FF-A sandbox driver */
> +#define SANDBOX_PARTITIONS_CNT (4)
> +
> +/* Binary data of services UUIDs emulated by the FF-A sandbox driver */
> +
> +/* 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_priv - 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_priv {
> +       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(struct udevice *dev, \
> +                                                             ffa_value_t *pargs, ffa_value_t *res)

drop that

[..]

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v9 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA
  2023-03-10 14:10                                                                                     ` [PATCH v9 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-03-10 20:49                                                                                       ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-03-10 20:49 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sudeep.holla, trini, u-boot, xueliang.zhong

Hi Abdellatif,

On Fri, 10 Mar 2023 at 06:10, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add functional test cases for the FF-A core driver
>
> These tests rely on the FF-A Sandbox driver which helps in
>  inspecting the FF-A core driver.
>
> 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>
>
> ---
> Changelog:
> ===============
>
> v9: align FF-A sandbox tests with FF-A discovery through DM
>
> v8:
>
>   * update partition_info_get() second argument to be an SP count
>   * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7: set the tests to use 64-bit direct messaging
>
> v4: align sandbox tests with the new FF-A driver interfaces
>  and new way of error handling
>
> v1: introduce sandbox tests
>
>  MAINTAINERS      |   1 +
>  test/dm/Makefile |   2 +
>  test/dm/ffa.c    | 380 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 383 insertions(+)
>  create mode 100644 test/dm/ffa.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 2b9d33e964..6939b832e4 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -275,6 +275,7 @@ F:  doc/usage/cmd/armffa.rst
>  F:     drivers/firmware/arm-ffa/
>  F:     include/arm_ffa.h
>  F:     include/sandbox_arm_ffa.h
> +F:     test/dm/ffa.c
>
>  ARM FREESCALE IMX
>  M:     Stefano Babic <sbabic@denx.de>
> diff --git a/test/dm/Makefile b/test/dm/Makefile
> index 7a79b6e1a2..b554b170db 100644
> --- a/test/dm/Makefile
> +++ b/test/dm/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0+
>  #
>  # Copyright (c) 2013 Google, Inc
> +# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
>
>  obj-$(CONFIG_UT_DM) += test-dm.o
>
> @@ -85,6 +86,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
>  obj-$(CONFIG_ACPI_PMC) += pmc.o
>  obj-$(CONFIG_DM_PMIC) += pmic.o
>  obj-$(CONFIG_DM_PWM) += pwm.o
> +obj-$(CONFIG_SANDBOX_FFA) += ffa.o
>  obj-$(CONFIG_QFW) += qfw.o
>  obj-$(CONFIG_RAM) += ram.o
>  obj-y += regmap.o
> diff --git a/test/dm/ffa.c b/test/dm/ffa.c
> new file mode 100644
> index 0000000000..d978feda72
> --- /dev/null
> +++ b/test/dm/ffa.c
> @@ -0,0 +1,380 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Functional tests for UCLASS_FFA  class
> + *
> + * 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 <console.h>
> +#include <dm.h>
> +#include <sandbox_arm_ffa.h>
> +#include "../../drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h"

I suppose this is OK, but you could put is in arch/sandbox/include/asm/ perhaps?

> +#include <dm/test.h>
> +#include <test/test.h>
> +#include <test/ut.h>
> +
> +/* Macros */
> +
> +#define LOG_MSG_SZ (100)
> +#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
> +
> +/* Functional tests for the UCLASS_FFA */
> +
> +static int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
> +{
> +       char cmd[LOG_CMD_SZ] = {0};
> +
> +       console_record_reset();
> +
> +       snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
> +       run_command(cmd, 0);
> +
> +       ut_assert_console_end();
> +
> +       return 0;
> +}
> +
> +static int check_fwk_version(struct ffa_priv *priv, struct sandbox_ffa_priv *sdx_priv,
> +                            struct unit_test_state *uts)
> +{
> +       if (priv->dscvry_info.fwk_version != sdx_priv->fwk_version) {
> +               char msg[LOG_MSG_SZ] = {0};
> +
> +               snprintf(msg, LOG_MSG_SZ,
> +                        "[%s]: Error: framework version: core = 0x%x , sandbox  = 0x%x", __func__,
> +                        priv->dscvry_info.fwk_version,
> +                       sdx_priv->fwk_version);
> +
> +               dm_test_ffa_log(uts, msg);
> +               return CMD_RET_FAILURE;
> +       }
> +       return 0;
> +}
> +
> +static int check_endpoint_id(struct ffa_priv *priv, struct unit_test_state *uts)
> +{
> +       if (priv->id) {
> +               char msg[LOG_MSG_SZ] = {0};
> +
> +               snprintf(msg, LOG_MSG_SZ,
> +                        "[%s]: Error: endpoint id: core = 0x%x", __func__, priv->id);
> +               dm_test_ffa_log(uts, msg);
> +               return CMD_RET_FAILURE;
> +       }
> +       return 0;
> +}
> +
> +static int check_rxtxbuf(struct ffa_priv *priv, struct unit_test_state *uts)
> +{
> +       if (!priv->pair.rxbuf && priv->pair.txbuf) {
> +               char msg[LOG_MSG_SZ] = {0};
> +
> +               snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = %p txbuf = %p", __func__,
> +                        priv->pair.rxbuf,
> +                        priv->pair.txbuf);
> +               dm_test_ffa_log(uts, msg);
> +               return CMD_RET_FAILURE;
> +       }
> +       return 0;
> +}
> +
> +static int check_features(struct ffa_priv *priv, struct unit_test_state *uts)
> +{
> +       char msg[LOG_MSG_SZ] = {0};
> +
> +       if (priv->pair.rxtx_min_pages != RXTX_4K &&
> +           priv->pair.rxtx_min_pages != RXTX_16K &&
> +           priv->pair.rxtx_min_pages != RXTX_64K) {
> +               snprintf(msg,
> +                        LOG_MSG_SZ,
> +                        "[%s]: Error: FFA_RXTX_MAP features = 0x%lx",
> +                        __func__,
> +                        priv->pair.rxtx_min_pages);
> +               dm_test_ffa_log(uts, msg);
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       return 0;
> +}
> +
> +static int check_rxbuf_mapped_flag(u32 queried_func_id,
> +                                  u8 rxbuf_mapped,
> +                                  struct unit_test_state *uts)
> +{
> +       char msg[LOG_MSG_SZ] = {0};
> +
> +       switch (queried_func_id) {
> +       case FFA_RXTX_MAP:
> +       {

Code style is sometimes a bit off. There should not be a {} around
this block, for example.

> +               if (rxbuf_mapped)
> +                       return 0;
> +               break;
> +       }
> +       case FFA_RXTX_UNMAP:
> +       {
> +               if (!rxbuf_mapped)
> +                       return 0;
> +               break;
> +       }
> +       default:
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__,
> +                (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP"));
> +       dm_test_ffa_log(uts, msg);
> +
> +       return CMD_RET_FAILURE;
> +}
> +
> +static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
> +{
> +       if (rxbuf_owned) {
> +               char msg[LOG_MSG_SZ] = {0};

Can you drop the assignment?

> +
> +               snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__);
> +               dm_test_ffa_log(uts, msg);
> +               return CMD_RET_FAILURE;
> +       }
> +       return 0;
> +}
> +
> +static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
> +{
> +       struct ffa_send_direct_data msg = {0};
> +       u8 cnt;
> +       struct udevice *ffa_dev = NULL;
> +       struct ffa_bus_ops *ffa_ops = NULL;

Unnecessary assignments aagin. Please look through and clean these up.

> +
> +       uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev);
> +       ut_assertok(!ffa_dev);
> +
> +       ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev);
> +       ut_assertok(!ffa_ops);

As mentioned earlier the operations should be in the uclass, rather
than having one uclass operation that returns the operations. I do
wonder which uclass you are copying, to end up with this?

> +
> +       ut_assertok(ffa_ops->sync_send_receive(ffa_dev, part_id, &msg, 1));
> +
> +       for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
> +               ut_assertok(((u64 *)&msg)[cnt] != 0xffffffffffffffff);
> +
> +       return 0;
> +}
> +
> +static int test_partitions_and_comms(const char *service_uuid,
> +                                    struct sandbox_ffa_priv *sdx_priv,
> +                                    struct unit_test_state *uts)
> +{
> +       u32 count = 0;
> +       struct ffa_partition_info *parts_info;
> +       u32 info_idx, exp_info_idx;
> +       int ret;
> +       struct udevice *ffa_dev = NULL;
> +       struct ffa_bus_ops *ffa_ops = NULL;
> +
> +       uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev);
> +       ut_assertok(!ffa_dev);

ut_assertnonnull(ffa_dev)

Also, please just use 'dev' as there is only one in this file

[..]

> +       /* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
> +       ret = test_partitions_and_comms(svc2_uuid, sdx_priv, uts);
> +       ut_assertok(ret != 0);

ut_assertok() is intended to check that something is 0, meaning no
error. It is confusing to use it for other things.

Here I think you want to say:

ut_assertok(ret)

?

If you want to assert something special, use ut_assert()

> +
> +       /* Test FFA_RX_RELEASE */
> +       rxbuf_flag = 1;
> +       ut_assertok(sandbox_ffa_query_core_state(sdx_dev, FFA_RX_RELEASE, &func_data));
> +       ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
> +
> +       /* Test FFA_RXTX_UNMAP */
> +       ut_assertok(ffa_ops->rxtx_unmap(ffa_dev));
> +
> +       rxbuf_flag = 1;
> +       ut_assertok(sandbox_ffa_query_core_state(sdx_dev, FFA_RXTX_UNMAP, &func_data));
> +       ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts));
> +
> +       return 0;
> +}
> +
> +DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
> +
> +static int dm_test_ffa_nack(struct unit_test_state *uts)
> +{
> +       struct ffa_priv *priv = NULL;
> +       struct sandbox_ffa_priv *sdx_priv = NULL;
> +       const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
> +       const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
> +       const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
> +       struct ffa_send_direct_data msg = {0};
> +       int ret;
> +       u32 count = 0;
> +       u16 part_id = 0;
> +       struct udevice *ffa_dev = NULL, *sdx_dev = NULL;
> +       struct ffa_bus_ops *ffa_ops = NULL;
> +
> +       /* Test probing the FF-A sandbox driver, then binding the FF-A bus driver */
> +       uclass_get_device_by_name(UCLASS_FFA, "sandbox_arm_ffa", &sdx_dev);
> +       ut_assertok(!sdx_dev);
> +
> +       /* Test probing the  FF-A bus driver */
> +       uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev);
> +       ut_assertok(!ffa_dev);
> +
> +       ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev);
> +       ut_assertok(!ffa_ops);
> +
> +       /* Get a pointer to the FF-A core and sandbox drivers private data */
> +       priv = dev_get_priv(ffa_dev);
> +       sdx_priv = dev_get_priv(sdx_dev);
> +
> +       /* Make sure private data pointers are retrieved */
> +       ut_assertok(priv == 0);
> +       ut_assertok(sdx_priv == 0);

Those two cannot fail :-)

> +
> +       /* Query partitions count using  invalid arguments */
> +       ret = ffa_ops->partition_info_get(ffa_dev, unvalid_svc_uuid, NULL, NULL);
> +       ut_assertok(ret != -EINVAL);

I think you are using ut_assertok() instead of ut_assert(). Please switch.

This one should be

ut_asserteq(-EINVAL, ret)

> +
> +       /* Query partitions count using an invalid UUID  string */
> +       ret = ffa_ops->partition_info_get(ffa_dev, unvalid_svc_uuid_str, &count, NULL);
> +       ut_assertok(ret != -EINVAL);
> +
> +       /* Query partitions count using an invalid UUID (no matching SP) */
> +       count = 0;
> +       ret = ffa_ops->partition_info_get(ffa_dev, unvalid_svc_uuid, &count, NULL);
> +       ut_assertok(count != 0);
> +
> +       /* Query partitions count using a valid UUID */
> +       count = 0;
> +       ret = ffa_ops->partition_info_get(ffa_dev, valid_svc_uuid, &count, NULL);
> +       /* Make sure partitions are detected */
> +       ut_assertok(ret != 0);
> +       ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE);
> +
> +       /* Send data to an invalid partition */
> +       ret = ffa_ops->sync_send_receive(ffa_dev, part_id, &msg, 1);
> +       ut_assertok(ret != -EINVAL);
> +
> +       /* Send data to a valid partition */
> +       part_id = priv->partitions.descs[0].info.id;
> +       ret = ffa_ops->sync_send_receive(ffa_dev, part_id, &msg, 1);
> +       ut_assertok(ret != 0);
> +
> +       return 0;
> +}
> +
> +DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
> --
> 2.25.1
>

This all looks find once you tidy up the nits.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v9 08/10] arm_ffa: introduce armffa command Sandbox test
  2023-03-10 14:10                                                                                     ` [PATCH v9 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2023-03-10 20:50                                                                                       ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-03-10 20:50 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sudeep.holla, trini, u-boot, xueliang.zhong

Hi Abdellatif,

On Fri, 10 Mar 2023 at 06:11, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add Sandbox test for the armffa command
>
> 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>
>
> ---
> Changelog:
> ===============
>
> v9: align the test with FF-A discovery through DM
>
> v4: drop use of helper APIs
>
> v1: introduce armffa command sandbox test
>
>  MAINTAINERS       |  1 +
>  test/cmd/Makefile |  2 ++
>  test/cmd/armffa.c | 39 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 42 insertions(+)
>  create mode 100644 test/cmd/armffa.c

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 6939b832e4..b36fb41668 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -275,6 +275,7 @@ F:  doc/usage/cmd/armffa.rst
>  F:     drivers/firmware/arm-ffa/
>  F:     include/arm_ffa.h
>  F:     include/sandbox_arm_ffa.h
> +F:     test/cmd/armffa.c
>  F:     test/dm/ffa.c
>
>  ARM FREESCALE IMX
> diff --git a/test/cmd/Makefile b/test/cmd/Makefile
> index 2ffde8703a..e74da56a29 100644
> --- a/test/cmd/Makefile
> +++ b/test/cmd/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0+
>  #
>  # Copyright (c) 2013 Google, Inc
> +# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
>
>  ifdef CONFIG_HUSH_PARSER
>  obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
> @@ -19,6 +20,7 @@ obj-$(CONFIG_CMD_PWM) += pwm.o
>  obj-$(CONFIG_CMD_SEAMA) += seama.o
>  ifdef CONFIG_SANDBOX
>  obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
> +obj-$(CONFIG_SANDBOX_FFA) += armffa.o
>  endif
>  obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
>  obj-$(CONFIG_CMD_WGET) += wget.o
> diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
> new file mode 100644
> index 0000000000..73c895f182
> --- /dev/null
> +++ b/test/cmd/armffa.c
> @@ -0,0 +1,39 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Test for armffa command
> + *
> + * 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 <sandbox_arm_ffa.h>
> +#include <string.h>
> +#include <dm/test.h>
> +#include <test/test.h>
> +#include <test/ut.h>
> +
> +#define PING_CMD_SIZE 19
> +
> +/* Basic test of 'armffa' command */
> +static int dm_test_armffa_cmd(struct unit_test_state *uts)
> +{
> +       char ping_cmd[PING_CMD_SIZE] = {0};
> +
> +       /* armffa getpart <UUID> */
> +       ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
> +
> +       snprintf(ping_cmd, PING_CMD_SIZE, "armffa ping 0x%x", SANDBOX_SP1_ID);
> +
> +       /* armffa ping <ID> */
> +       ut_assertok(run_command(ping_cmd, 0));
> +
> +       /* armffa devlist */
> +       ut_assertok(run_command("armffa devlist", 0));
> +
> +       return CMD_RET_SUCCESS;

return 0

(this isn't even a command, it is a test)

> +}
> +
> +DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
> --
> 2.25.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v9 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-03-10 14:10                                                                                     ` [PATCH v9 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-03-10 20:50                                                                                       ` Simon Glass
  2023-03-14 17:05                                                                                         ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-03-10 20:50 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sudeep.holla, trini, u-boot, xueliang.zhong,
	Gowtham Suresh Kumar

Hi Abdellatif,

On Fri, 10 Mar 2023 at 06:11, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add MM communication support using FF-A transport
>
> This feature allows accessing MM partitions services through
> EFI MM communication protocol. MM partitions such as StandAlonneMM
> or smm-gateway secure partitions which reside in secure world.
>
> An MM shared buffer and a door bell event are used to exchange
> the data.
>
> The data is used by EFI services such as GetVariable()/SetVariable()
> and copied from the communication buffer to the MM shared buffer.
>
> The secure partition is notified about availability of data in the
> MM shared buffer by an FF-A message (door bell).
>
> On such event, MM SP can read the data and updates the MM shared
> buffer with the response data.
>
> The response data is copied back to the communication buffer and
> consumed by the EFI subsystem.
>
> MM communication protocol supports FF-A 64-bit direct messaging.
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>
>
> ---
> Changelog:
> ===============
>
> v9: align how FF-A is used with FF-A discovery through DM
>
> v8:
>
> * isolate the compilation choices between FF-A and OP-TEE
> * update partition_info_get() second argument to be an SP count
> * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7:
>
> * set the MM door bell event to use 64-bit direct messaging
> * issue a compile time error when one of these macros are not found :
>   FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
> * make mm_sp_svc_uuid static
> * replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
> * improve use of unmap_sysmem() in ffa_mm_communicate()
>
> v6:
>
> * add FF-A runtime discovery at MM communication level
> * drop EFI runtime support for FF-A MM communication
> * revert the changes in include/mm_communication.h for
>   efi_mm_communicate_header and smm_variable_access structures
>
> v4:
>
> * use the new FF-A driver interfaces
> * discover MM partitions at runtime
> * copy FF-A driver private data to EFI runtime section at
>   ExitBootServices()
> * drop use of FFA_ERR_STAT_SUCCESS error code
> * replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
>   in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
> * revert the error log in mm_communicate() in case of failure
> * remove packed attribute from efi_mm_communicate_header and
>   smm_variable_communicate_header
>
> v2:
>
> * set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings
>
> v1:
>
> * introduce FF-A MM communication
>
>  include/mm_communication.h        |   6 +
>  lib/efi_loader/Kconfig            |  14 +-
>  lib/efi_loader/efi_variable_tee.c | 317 +++++++++++++++++++++++++++++-
>  3 files changed, 331 insertions(+), 6 deletions(-)
>
> diff --git a/include/mm_communication.h b/include/mm_communication.h
> index e65fbde60d..87509fec3f 100644
> --- a/include/mm_communication.h
> +++ b/include/mm_communication.h
> @@ -6,6 +6,9 @@
>   *  Copyright (c) 2017, Intel Corporation. All rights reserved.
>   *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
>   *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
> + *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *    Authors:
> + *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>
>  #ifndef _MM_COMMUNICATION_H_
> @@ -13,6 +16,9 @@
>
>  #include <part_efi.h>
>
> +/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
> +#define MM_SP_UUID     "33d532ed-e699-0942-c09c-a798d9cd722d"
> +
>  /*
>   * Interface to the pseudo Trusted Application (TA), which provides a
>   * communication channel with the Standalone MM (Management Mode)
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index c5835e6ef6..08a6b84101 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
>           stored as file /ubootefi.var on the EFI system partition.
>
>  config EFI_MM_COMM_TEE
> -       bool "UEFI variables storage service via OP-TEE"
> -       depends on OPTEE
> +       bool "UEFI variables storage service via the trusted world"
> +       depends on OPTEE || ARM_FFA_TRANSPORT
>         help
> +         Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
> +         When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> +         When using the u-boot FF-A  driver any MM SP is supported.
> +
>           If OP-TEE is present and running StandAloneMM, dispatch all UEFI
>           variable related operations to that. The application will verify,
>           authenticate and store the variables on an RPMB.
>
> +         When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> +         operations to the MM SP running in the secure world.
> +         A door bell mechanism is used to notify the SP when there is data in the shared
> +         MM buffer. The data is copied by u-boot to the shared buffer before issuing
> +         the door bell event.
> +
>  config EFI_VARIABLE_NO_STORE
>         bool "Don't persist non-volatile UEFI variables"
>         help
> diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> index dfef18435d..86207f1ff2 100644
> --- a/lib/efi_loader/efi_variable_tee.c
> +++ b/lib/efi_loader/efi_variable_tee.c
> @@ -4,9 +4,14 @@
>   *
>   *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
>   *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
> + *  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 <efi.h>
>  #include <efi_api.h>
>  #include <efi_loader.h>
> @@ -15,6 +20,36 @@
>  #include <malloc.h>
>  #include <mm_communication.h>
>
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))

Please avoid excluding code unless you need to

> +
> +#include <arm_ffa.h>
> +#include <cpu_func.h>
> +#include <mapmem.h>
> +
> +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_SIZE 0

Shouldn't that info be in the DT?

> +#endif
> +
> +#ifndef FFA_SHARED_MM_BUFFER_OFFSET
> +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_OFFSET 0
> +#endif
> +
> +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_ADDR 0
> +#endif
> +
> +/* MM return codes */
> +#define MM_SUCCESS (0)
> +
> +static const char *mm_sp_svc_uuid = MM_SP_UUID;
> +
> +static u16 mm_sp_id;
> +
> +#endif
> +
>  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
>  static efi_uintn_t max_buffer_size;    /* comm + var + func + data */
>  static efi_uintn_t max_payload_size;   /* func + data */
> @@ -24,6 +59,7 @@ struct mm_connection {
>         u32 session;
>  };
>
> +#if (IS_ENABLED(CONFIG_OPTEE))

same here

>  /**
>   * get_connection() - Retrieve OP-TEE session for a specific UUID.
>   *
> @@ -143,13 +179,269 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
>
>         return ret;
>  }
> +#endif
> +
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))

and here

> +
> +/**
> + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> + *
> + * Notifies the MM partition in the trusted world that
> + * data is available in the shared buffer.
> + * This is a blocking call during which trusted world has exclusive access
> + * to the MM shared buffer.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_notify_mm_sp(void)
> +{
> +       struct ffa_send_direct_data msg = {0};
> +       int ret;
> +       int sp_event_ret = -1;
> +       struct udevice *ffa_dev = NULL;
> +       struct ffa_bus_ops *ffa_ops = NULL;
> +
> +       uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev);

uclass_first_device()

> +       if (!ffa_dev) {
> +               log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
> +               return -ENODEV;
> +       }
> +
> +       ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev);
> +       if (!ffa_ops) {
> +               log_err("EFI: Invalid FF-A ops, notify MM SP failure\n");
> +               return -EINVAL;
> +       }
> +
> +       msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
> +
> +       ret = ffa_ops->sync_send_receive(ffa_dev, mm_sp_id, &msg, 1);
> +       if (ret != 0)
> +               return ret;
> +
> +       sp_event_ret = msg.data0; /* x3 */
> +
> +       if (sp_event_ret == MM_SUCCESS)
> +               return 0;
> +
> +       /*
> +        * Failure to notify the MM SP
> +        */

/* Failure ... */

> +
> +       return -EACCES;
> +}
> +
> +/**
> + * ffa_discover_mm_sp_id() - Query the MM partition ID
> + *
> + * Use the FF-A driver to get the MM partition ID.
> + * If multiple partitions are found, use the first one.
> + * This is a boot time function.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_discover_mm_sp_id(void)
> +{
> +       u32 count = 0;
> +       int ret;
> +       struct ffa_partition_info *parts_info;
> +       struct udevice *ffa_dev = NULL;
> +       struct ffa_bus_ops *ffa_ops = NULL;
> +
> +       uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev);
> +       if (!ffa_dev) {
> +               log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
> +               return -ENODEV;
> +       }
> +
> +       ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev);
> +       if (!ffa_ops) {
> +               log_err("EFI: Invalid FF-A ops, MM SP discovery failure\n");
> +               return -EINVAL;
> +       }
> +
> +       /* Get from the driver the count of the SPs matching the UUID */
> +       ret = ffa_ops->partition_info_get(ffa_dev, mm_sp_svc_uuid, &count, NULL);
> +       if (ret != 0) {
> +               log_err("EFI: Failure in querying SPs count (%d), MM SP discovery failure\n", ret);
> +               return ret;
> +       }
> +
> +       if (!count) {
> +               log_info("EFI: No MM partition found\n");
> +               return ret;
> +       }
> +
> +       /* Pre-allocate a buffer to be filled by the driver with ffa_partition_info structs */
> +
> +       log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
> +
> +       parts_info = calloc(count, sizeof(*parts_info));
> +       if (!parts_info)
> +               return -ENOMEM;
> +
> +       /* Ask the driver to fill the buffer with the SPs info */
> +       ret = ffa_ops->partition_info_get(ffa_dev, mm_sp_svc_uuid, &count, parts_info);
> +       if (ret) {
> +               log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
> +               free(parts_info);
> +               return ret;
> +       }
> +
> +       /* MM SPs found , use the first one */
> +
> +       mm_sp_id = parts_info[0].id;
> +
> +       log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
> +
> +       free(parts_info);
> +
> +       return 0;
> +}
> +
> +/**
> + * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
> + * @comm_buf:          locally allocated communication buffer used for rx/tx
> + * @dsize:                             communication buffer size
> + *
> + * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
> + * that there is data to read from the shared buffer.
> + * Communication with the MM SP is performed using FF-A transport.
> + * On the event, MM SP can read the data from the buffer and
> + * update the MM shared buffer with response data.
> + * The response data is copied back to the communication buffer.
> + *
> + * Return:
> + *
> + * EFI status code
> + */
> +static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
> +{
> +       ulong tx_data_size;
> +       int ffa_ret;
> +       efi_status_t efi_ret;
> +       struct efi_mm_communicate_header *mm_hdr;
> +       void *virt_shared_buf;
> +
> +       if (!comm_buf)
> +               return EFI_INVALID_PARAMETER;
> +
> +       /* Discover MM partition ID at boot time */
> +       if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
> +               log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
> +               return EFI_UNSUPPORTED;
> +       }
> +
> +       mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> +       tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
> +
> +       if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
> +               return EFI_INVALID_PARAMETER;
> +
> +       /* Copy the data to the shared buffer */
> +
> +       virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
> +       memcpy(virt_shared_buf, comm_buf, tx_data_size);
> +
> +       /*
> +        * The secure world might have cache disabled for
> +        * the device region used for shared buffer (which is the case for Optee).
> +        * In this case, the secure world reads the data from DRAM.
> +        * Let's flush the cache so the DRAM is updated with the latest data.
> +        */
> +       #ifdef CONFIG_ARM64
> +       invalidate_dcache_all();

indent, I think?

> +       #endif
> +
> +       /* Announce there is data in the shared buffer */
> +
> +       ffa_ret = ffa_notify_mm_sp();
> +
> +       switch (ffa_ret) {
> +       case 0:
> +       {

Don't we normally put the { at the end of the previous line?


> +               ulong rx_data_size;
> +               /* Copy the MM SP response from the shared buffer to the communication buffer */
> +               rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> +                       sizeof(efi_guid_t) +
> +                       sizeof(size_t);
> +
> +               if (rx_data_size > comm_buf_size) {
> +                       efi_ret = EFI_OUT_OF_RESOURCES;
> +                       break;
> +               }
> +
> +               memcpy(comm_buf, virt_shared_buf, rx_data_size);
> +               efi_ret = EFI_SUCCESS;
> +               break;
> +       }
> +       case -EINVAL:
> +               efi_ret = EFI_DEVICE_ERROR;
> +               break;
> +       case -EPERM:
> +               efi_ret = EFI_INVALID_PARAMETER;
> +               break;
> +       case -EACCES:
> +               efi_ret = EFI_ACCESS_DENIED;
> +               break;
> +       case -EBUSY:
> +               efi_ret = EFI_OUT_OF_RESOURCES;
> +               break;
> +       default:
> +               efi_ret = EFI_ACCESS_DENIED;
> +       }
> +
> +       unmap_sysmem(virt_shared_buf);
> +       return efi_ret;
> +}
> +#endif
> +
> +/**
> + * select_ffa_mm_comms() - checks FF-A support availability
> + *
> + * Making sure FF-A is compiled in. If that's the case try to make sure
> + * the FF-A bus is probed successfully which means FF-A communication
> + * with secure world works and ready to be used.
> + *
> + * Return:
> + *
> + * 0: FF-A ready for use. Otherwise, failure
> + */
> +static efi_status_t select_ffa_mm_comms(void)
> +{
> +       efi_status_t ret = EFI_UNSUPPORTED;
> +
> +       if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) {
> +               struct udevice *dev = NULL;
> +
> +               uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &dev);
> +               if (!dev) {
> +                       log_err("EFI: Cannot find FF-A bus device, cannot select FF-A comms\n");
> +                       ret = EFI_NOT_READY;
> +               } else {
> +                       ret = EFI_SUCCESS;
> +               }
> +       }
> +
> +       return ret;
> +}
>
>  /**
> - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
speeding

> + * mm_communicate() - Adjust the communication buffer to the MM SP and send
>   * it to OP-TEE
>   *
> - * @comm_buf:          locally allocted communcation buffer

spelling

> + * @comm_buf:          locally allocated communication buffer
>   * @dsize:             buffer size
> + *
> + * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
> + * The comm_buf format is the same for both partitions.
> + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> + * When using the u-boot FF-A  driver, any MM SP is supported.
> + *
>   * Return:             status code
>   */
>  static efi_status_t (u8 *comm_buf, efi_uintn_t dsize)
> @@ -162,7 +454,17 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>         mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
>         var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;

smm_var_comms_hdr would be a lot shorter!


>
> -       ret = optee_mm_communicate(comm_buf, dsize);
> +       ret = select_ffa_mm_comms();
> +       if (ret != EFI_SUCCESS) {
> +#if (IS_ENABLED(CONFIG_OPTEE))
> +               ret = optee_mm_communicate(comm_buf, dsize);
> +#endif
> +       } else {
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +               ret = ffa_mm_communicate(comm_buf, dsize);
> +#endif
> +       }
> +
>         if (ret != EFI_SUCCESS) {
>                 log_err("%s failed!\n", __func__);
>                 return ret;
> @@ -258,6 +560,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
>                 goto out;
>         }
>         *size = var_payload->size;
> +
> +       #if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +               if (*size > FFA_SHARED_MM_BUFFER_SIZE)
> +                       *size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE  -
> +                               MM_VARIABLE_COMMUNICATE_SIZE;
> +       #endif
> +
>         /*
>          * There seems to be a bug in EDK2 miscalculating the boundaries and
>          * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> @@ -697,7 +1006,7 @@ void efi_variables_boot_exit_notify(void)
>                 ret = EFI_NOT_FOUND;
>
>         if (ret != EFI_SUCCESS)
> -               log_err("Unable to notify StMM for ExitBootServices\n");
> +               log_err("Unable to notify the MM partition for ExitBootServices\n");
>         free(comm_buf);
>
>         /*
> --
> 2.25.1
>

Regards,
Simonn

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v9 00/10] introduce Arm FF-A support
  2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                       ` (9 preceding siblings ...)
  2023-03-10 14:10                                                                                     ` [PATCH v9 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
@ 2023-03-10 20:50                                                                                     ` Simon Glass
  2023-03-28 16:11                                                                                       ` [PATCH v10 " Abdellatif El Khlifi
  10 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-03-10 20:50 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sudeep.holla, trini, u-boot, xueliang.zhong

Hi Abdellatif,

On Fri, 10 Mar 2023 at 06:12, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
>
> FF-A describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World. These interfaces enable a pair of
> software sandboxes to communicate with each other. A sandbox aka partition could
> be a VM in the Normal or Secure world, an application in S-EL0, or a
> Trusted OS in S-EL1.
>
> FF-A is a discoverable bus and similar to architecture features.
> FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> by the PSCI driver.
>
>    => dm tree
>
>     Class     Index  Probed  Driver                Name
>    -----------------------------------------------------------
>    ...
>     firmware      0  [ + ]   psci                      |-- psci
>     ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
>    ...
>
> Clients are able to probe then use the FF-A bus by calling the DM class
> searching APIs (e.g: uclass_get_device_by_name).
>
> This implementation of the specification provides support for Aarch64.
>
> The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
>
>     - Discover the presence of secure partitions (SPs) of interest
>     - Access an SP's service through communication protocols
>       e.g. EFI MM communication protocol
>
> The FF-A support provides the following features:
>
>     - Being generic by design and can be used by any Arm 64-bit platform
>     - The FF-A core driver
>     - The driver provides driver operations to be used by clients to access the FF-A bus
>     - FF-A driver can be compiled and used without EFI
>     - Support for SMCCCv1.2 x0-x17 registers
>     - Support for SMC32 calling convention
>     - Support for 32-bit and 64-bit FF-A direct messaging
>     - A new command called armffa is provided as an example of how to access the
>       FF-A bus
>     - An FF-A Sandbox driver is provided with test cases
>     - Support for FF-A MM communication (compatible with EFI boot time)
>     - Enabling FF-A and MM communication in Corstone1000 platform as a use case
>
> For more details about the FF-A core driver please refer to [B] and refer to [C] for
> how to use the armffa command.
>
> Please find at [D] an example of the expected boot logs when enabling
> FF-A support for a platform. In this example the platform is
> Corstone1000. But it can be any Arm 64-bit platform.
>
> Changelog of the major changes:
> ===========================
>
> v9:
>
> * integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
> * align FF-A sandbox driver with FF-A discovery through DM
> * use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
> * add documentation for the armffa command: doc/usage/cmd/armffa.rst
> * introduce testcase for uuid_str_to_le_bin

This version looks a lot better. Things I noticed:

- fix up uclass to use operations
- tidy up emulator binding to use DT

Both should be fairly easy.

Other than that I just have code-style nits.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v9 06/10] arm_ffa: introduce the FF-A Sandbox driver
  2023-03-10 20:49                                                                                       ` Simon Glass
@ 2023-03-14 12:55                                                                                         ` Abdellatif El Khlifi
  2023-03-14 17:59                                                                                         ` Abdellatif El Khlifi
  1 sibling, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-14 12:55 UTC (permalink / raw)
  To: Simon Glass
  Cc: robh, trini, ilias.apalodimas, achin.gupta, xueliang.zhong, u-boot, nd

On Fri, Mar 10, 2023 at 12:49:57PM -0800, Simon Glass wrote:
> Hi Abdellatif,
> 
> On Fri, 10 Mar 2023 at 06:10, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > 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>
> >
> > ---
> > Changelog:
> > ===============
> >
> > v9: align FF-A sandbox driver with FF-A discovery through DM
> >
> > v8: update ffa_bus_prvdata_get() to return a pointer rather than
> >     a pointer address
> >
> > v7: state that sandbox driver supports only 64-bit direct messaging
> >
> > v4: align sandbox driver with the new FF-A driver interfaces
> >     and new way of error handling
> >
> > v1: introduce the sandbox driver
> >
> >  MAINTAINERS                                   |   1 +
> >  arch/sandbox/dts/sandbox.dtsi                 |   4 +
> >  arch/sandbox/dts/test.dts                     |   4 +
> >  configs/sandbox64_defconfig                   |   2 +
> >  configs/sandbox_defconfig                     |   2 +
> >  doc/arch/arm64.ffa.rst                        |   4 +
> >  doc/arch/sandbox/sandbox.rst                  |   1 +
> >  drivers/firmware/arm-ffa/Kconfig              |  11 +-
> >  drivers/firmware/arm-ffa/Makefile             |   1 +
> >  drivers/firmware/arm-ffa/core.c               |  36 +-
> >  drivers/firmware/arm-ffa/sandbox.c            | 610 ++++++++++++++++++
> >  .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   | 129 ++++
> >  include/arm_ffa.h                             |   5 +-
> >  include/sandbox_arm_ffa.h                     | 124 ++++
> >  14 files changed, 928 insertions(+), 6 deletions(-)
> >  create mode 100644 drivers/firmware/arm-ffa/sandbox.c
> >  create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> >  create mode 100644 include/sandbox_arm_ffa.h
> >
> 
> Could you use 80 columns where possible? There seem to be a lot of
> things that extend beyond that without much of a reason.
> 
> Also you can use 'ulong' instead of 'unsigned long'. It is less
> verbose and a U-Boot standard.
> 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 18e9c2ce99..2b9d33e964 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -274,6 +274,7 @@ 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..059c273277 100644
> > --- a/arch/sandbox/dts/sandbox.dtsi
> > +++ b/arch/sandbox/dts/sandbox.dtsi
> > @@ -445,6 +445,10 @@
> >         thermal {
> >                 compatible = "sandbox,thermal";
> >         };
> > +
> > +       sandbox_arm_ffa {
> > +               compatible = "sandbox,arm_ffa";
> > +       };
> >  };
> >
> >  &cros_ec {
> > diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> > index d72d7a567a..11dc6ed0d9 100644
> > --- a/arch/sandbox/dts/test.dts
> > +++ b/arch/sandbox/dts/test.dts
> > @@ -1802,6 +1802,10 @@
> >                 compatible = "u-boot,fwu-mdata-gpt";
> >                 fwu-mdata-store = <&mmc0>;
> >         };
> > +
> > +       sandbox_arm_ffa {
> > +               compatible = "sandbox,arm_ffa";
> > +       };
> 
> I see that you have this, so the driver should bind automatically.
> 
> Is the problem that you are trying to bind the sandbox emulator?
> Again, you can actually add that to the DT. See how this works for
> i2c, SPI, PCI, for example.
> 
> >  };
> >
> >  #include "sandbox_pmic.dtsi"
> > diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
> > index ccbc18aad0..35d4676cf7 100644
> > --- a/configs/sandbox64_defconfig
> > +++ b/configs/sandbox64_defconfig
> > @@ -259,3 +259,5 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
> >  CONFIG_UNIT_TEST=y
> >  CONFIG_UT_TIME=y
> >  CONFIG_UT_DM=y
> > +CONFIG_ARM_FFA_TRANSPORT=y
> > +CONFIG_SANDBOX_FFA=y
> > diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
> > index a0fbdad20a..8aab8dda31 100644
> > --- a/configs/sandbox_defconfig
> > +++ b/configs/sandbox_defconfig
> > @@ -336,3 +336,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/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> > index 8fad9ef3d0..555ee9a6ae 100644
> > --- a/doc/arch/arm64.ffa.rst
> > +++ b/doc/arch/arm64.ffa.rst
> > @@ -64,6 +64,10 @@ CONFIG_ARM_FFA_TRANSPORT
> >      Enables the FF-A bus driver. Turn this on if you want to use FF-A
> >      communication.
> >
> > +CONFIG_SANDBOX_FFA
> > +    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
> > +    Sandbox and provides functional tests for FF-A.
> 
> OK that is why I am confused. Please don't call this a driver. It is
> an emulator. When you have an emulator and a driver for the same thing
> it gets confusing.
> 
> > +
> >  FF-A ABIs under the hood
> >  ---------------------------------------
> >
> > diff --git a/doc/arch/sandbox/sandbox.rst b/doc/arch/sandbox/sandbox.rst
> > index cd7f8a2cb0..c5df372e00 100644
> > --- a/doc/arch/sandbox/sandbox.rst
> > +++ b/doc/arch/sandbox/sandbox.rst
> > @@ -200,6 +200,7 @@ Supported Drivers
> >
> >  U-Boot sandbox supports these emulations:
> >
> > +- Arm FF-A
> >  - Block devices
> >  - Chrome OS EC
> >  - GPIO
> > diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> > index 2cfd7ef5fc..b5430eb6f4 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
> > @@ -32,3 +32,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 c8d83b4bc9..d22c1ba609 100644
> > --- a/drivers/firmware/arm-ffa/Makefile
> > +++ b/drivers/firmware/arm-ffa/Makefile
> > @@ -6,3 +6,4 @@
> >  #   Abdellatif El Khlifi <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/core.c b/drivers/firmware/arm-ffa/core.c
> > index 2210f5343c..0d2e6ff0d4 100644
> > --- a/drivers/firmware/arm-ffa/core.c
> > +++ b/drivers/firmware/arm-ffa/core.c
> > @@ -1042,6 +1042,7 @@ bool ffa_try_discovery(void)
> >         return true;
> >  }
> >
> > +#if !CONFIG_IS_ENABLED(SANDBOX_FFA)
> 
> We should not need #ifdefs here. The sandbox driver is just another
> driver, just like there is the ARM driver. We select the correct one
> using the devicetree and everything just works.
> 
> >  /**
> >   * __arm_ffa_fn_smc() - SMC wrapper
> >   * @args: FF-A ABI arguments to be copied to Xn registers
> > @@ -1069,6 +1070,7 @@ void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
> >   * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
> >   * So, the legacy SMC invocation is not used.
> >   *
> > + * In Sandbox mode sandbox_arm_ffa is used to test arm_ffa driver.
> >   * Return:
> >   *
> >   * 0 on success. Otherwise, failure
> > @@ -1088,6 +1090,30 @@ ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
> >         .driver_name = FFA_DRV_NAME,
> >         .is_supported = ffa_bus_is_supported,
> >  };
> > +#else
> > +/* SANDBOX_FFA */
> > +
> > +/**
> > + * ffa_bind() - The driver bind function
> > + * @dev:       the arm_ffa device
> > + * When using sandbox tries to discover the emulated FF-A bus.
> > + * Return:
> > + *
> > + * 0 on success.
> > + */
> > +static int ffa_bind(struct udevice *dev)
> 
> I don't think this is binding anything. How about ffa_get_dev() ?
> 
> > +{
> > +       bool ret;
> > +
> > +       log_info("[FFA] binding the device\n");
> > +
> > +       ret = ffa_try_discovery();
> > +       if (ret)
> > +               return 0;
> > +       else
> > +               return -ENODEV;
> > +}
> > +#endif
> >
> >  /**
> >   * ffa_set_smc_conduit() - Set the SMC conduit
> > @@ -1101,7 +1127,12 @@ ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
> >   */
> >  static int ffa_set_smc_conduit(void)
> >  {
> > -       dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc;
> > +#if CONFIG_IS_ENABLED(SANDBOX_FFA)
> > +               dscvry_info.invoke_ffa_fn = sandbox_arm_ffa_smccc_smc;
> > +               log_info("[FFA] Using SMC emulation\n");
> > +#else
> > +               dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc;
> > +#endif
> 
> This needs to be reworked to go through the uclass to the correct
> driver. Basically you need an ARM driver and a sandbox driver (which
> attaches to the emulator).
> 
> There should not be #idefs in this sort of code...driver model should
> handle it. See other uclasses for examples.
> 
> >
> >         log_info("[FFA] Conduit is SMC\n");
> >
> > @@ -1246,4 +1277,7 @@ U_BOOT_DRIVER(arm_ffa) = {
> >         .remove = ffa_remove,
> >         .unbind = ffa_unbind,
> >         .ops            = &ffa_ops,
> > +#if CONFIG_IS_ENABLED(SANDBOX_FFA)
> > +       .bind           = ffa_bind,
> 
> Can drop this
> 
> > +#endif
> >  };
> > diff --git a/drivers/firmware/arm-ffa/sandbox.c b/drivers/firmware/arm-ffa/sandbox.c
> 
> sandbox_emul.c pehaps?
> 
> I am pretty sure this is an emulator
> 
> > new file mode 100644
> > index 0000000000..84c2fc929f
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/sandbox.c
> > @@ -0,0 +1,610 @@
> > +// 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 <dm/device-internal.h>
> > +#include <dm/lists.h>
> > +#include <dm/root.h>
> > +#include <linux/errno.h>
> > +#include <linux/sizes.h>
> > +#include "sandbox_arm_ffa_priv.h"
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/* The partitions (SPs) table */
> > +static struct ffa_partition_desc sandbox_partitions[SANDBOX_PARTITIONS_CNT] = {
> > +       {
> > +               .info = { .id = SANDBOX_SP1_ID, .exec_ctxt = 0x5687, .properties = 0x89325621 },
> > +               .sp_uuid = {
> > +                       .a1 = SANDBOX_SERVICE1_UUID_A1,
> > +                       .a2 = SANDBOX_SERVICE1_UUID_A2,
> > +                       .a3 = SANDBOX_SERVICE1_UUID_A3,
> > +                       .a4 = SANDBOX_SERVICE1_UUID_A4,
> > +               }
> > +       },
> > +       {
> > +               .info = { .id = SANDBOX_SP2_ID, .exec_ctxt = 0x9587, .properties = 0x45325621 },
> > +               .sp_uuid = {
> > +                       .a1 = SANDBOX_SERVICE2_UUID_A1,
> > +                       .a2 = SANDBOX_SERVICE2_UUID_A2,
> > +                       .a3 = SANDBOX_SERVICE2_UUID_A3,
> > +                       .a4 = SANDBOX_SERVICE2_UUID_A4,
> > +               }
> > +       },
> > +       {
> > +               .info = { .id = SANDBOX_SP3_ID, .exec_ctxt = 0x7687, .properties = 0x23325621 },
> > +               .sp_uuid = {
> > +                       .a1 = SANDBOX_SERVICE1_UUID_A1,
> > +                       .a2 = SANDBOX_SERVICE1_UUID_A2,
> > +                       .a3 = SANDBOX_SERVICE1_UUID_A3,
> > +                       .a4 = SANDBOX_SERVICE1_UUID_A4,
> > +               }
> > +       },
> > +       {
> > +               .info = { .id = SANDBOX_SP4_ID, .exec_ctxt = 0x1487, .properties = 0x70325621 },
> > +               .sp_uuid = {
> > +                       .a1 = SANDBOX_SERVICE2_UUID_A1,
> > +                       .a2 = SANDBOX_SERVICE2_UUID_A2,
> > +                       .a3 = SANDBOX_SERVICE2_UUID_A3,
> > +                       .a4 = SANDBOX_SERVICE2_UUID_A4,
> > +               }
> > +       }
> > +
> > +};
> > +
> > +/* Driver functions */
> > +
> > +/**
> > + * sandbox_ffa_version() - Emulated FFA_VERSION handler function
> > + * @dev:       the sandbox FF-A device
> > + * @{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)
> 
> Instead of the macro can you write this out in full? It defeats ctags, etc.
> 
> > +{
> > +       struct sandbox_ffa_priv *priv = dev_get_priv(dev);
> > +
> > +       priv->fwk_version = FFA_VERSION_1_0;
> > +       res->a0 = priv->fwk_version;
> 
> Where is res defined?
> 
> > +
> > +       /* 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
> > + * @dev:       the sandbox FF-A device
> > + * @{a0-a7} , res: The SMC call arguments and return structure.
> > + *
> > + * This is the function that emulates FFA_ID_GET FF-A function.
> 
> s/This is the function that e/E/g
> 
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +SANDBOX_SMC_FFA_ABI(ffa_id_get)
> > +{
> > +       struct sandbox_ffa_priv *priv = dev_get_priv(dev);
> > +
> > +       res->a0 = FFA_SMC_32(FFA_SUCCESS);
> > +       res->a1 = 0;
> > +
> > +       priv->id = NS_PHYS_ENDPOINT_ID;
> > +       res->a2 = priv->id;
> > +
> > +       /* x3-x7 MBZ */
> > +       memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long));
> > +
> > +       return 0;
> > +}
> > +
> > +/**
> > + * sandbox_ffa_features() - Emulated FFA_FEATURES handler function
> > + * @dev:       the sandbox FF-A device
> > + * @{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));
> > +               log_err("[FFA] [Sandbox] FF-A interface 0x%lx not implemented\n", pargs->a1);
> 
> return -ENOSYS
> 
> > +       }
> > +
> > +       res->a1 = 0;
> > +
> > +       return 0;
> > +}
> > +
> 
> [..]
> 
> > +SANDBOX_SMC_FFA_ABI(ffa_msg_send_direct_req)
> > +{
> > +       u16 part_id;
> > +       struct sandbox_ffa_priv *priv = dev_get_priv(dev);
> > +
> > +       part_id = GET_DST_SP_ID(pargs->a1);
> > +
> > +       if ((GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id) ||
> 
> drop extra brackets
> 
> > +           !sandbox_ffa_sp_valid(dev, 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(priv->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;
> 
> Would -1UL work?
> 
> > +
> > +       return 0;
> > +}
> > +
> 
> [..]
> 
> > +static int sandbox_ffa_probe(struct udevice *dev)
> > +{
> > +       struct udevice *child_dev = NULL;
> > +       int ret;
> > +
> > +       ret = device_bind_driver(dev, FFA_DRV_NAME, FFA_DRV_NAME, &child_dev);
> 
> Is this binding the emulator? Add it to the DT instead.
> 
> If you put
> 
> .post_bind = dm_scan_fdt_dev()
> 
> in your uclass (like spi-uclass.c does) then it will binding
> child-node devices automatically. Then you can make your emulator a
> child node.
> 

Hi Simon,

Thanks for the comments. I'm happy to address them.

I'd like to explain the following points:

1/ The FF-A core driver is the driver that interacts with secure world. The driver is implemented in drivers/firmware/arm-ffa/core.c

The FF-A sandbox driver is the driver used to emulate the FF-A side of the secure world and interacts with the core driver.
The sandbox driver is implemented in drivers/firmware/arm-ffa/sandbox.c

If you prefer we call it FF-A sandbox emulator, please let me know.
I'm calling it sandbox driver based on what the checkpatch script is suggesting.

2/ As we agreed with Rob, in the patchset v9 , FF-A is seen as an architecture feature and is discovered by software.
The root device tree node is the PSCI device and the architecture features are children of the PSCI device.

When the PSCI driver is probed, it tries to discover the architecture features (including FF-A).
When the FF-A discovery succeeds, PSCI creates the FF-A device as a child of PSCI device, and binds the FF-A core driver with the FF-A core device.

This is done here [1] using device_bind_driver().

   => dm tree

    Class     Index  Probed  Driver                Name
   -----------------------------------------------------------
   ...
    firmware      0  [ + ]   psci                      |-- psci
    ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa

Since PSCI is not supported in sandbox, we can not use PSCI driver to discover the emulated FF-A framework.
In place of the PSCI driver, FF-A discovery and binding is done in the FF-A sandbox driver at probe level (same way as PSCI).
The FF-A core device is bound and set as a child of the FF-A sandbox device.
This garantees the same behaviour as the real use case.

Is it OK to keep it like done for the PSCI please ? ( using device_bind_driver() )

3/ FF-A core device and FF-A sandbox device both belong to UCLASS_FFA.

In a real use case, there is 1 FF-A device (arm_ffa). However, when using sandbox there are 2 devices:

FF-A core device (arm_ffa)
FF-A sandbox device (sandbox_arm_ffa)

So, there is a good reason to use uclass_get_device_by_name() which garantees that we probe the right device.
In sandbox mode, the sandbox FF-A device should be probed first since it is responsible of discovering and binding the FF-A core device.
This is as close as possible to what PSCI driver does.

4/ In a real use case, we only need to use the PSCI device tree node as parent. In sandbox mode, we need to use the FF-A sandbox device tree node as parent.
5/ I'm happy to update the core driver operations as you suggested, thanks for the comments.
6/ I'm happy to rename the devices to arm-ffa and sandbox-arm-ffa

[1]: https://github.com/u-boot/u-boot/blob/master/drivers/firmware/psci.c#L158

Cheers
Abdellatif

> > +       if (ret) {
> > +               pr_err("%s was not bound: %d, aborting\n", FFA_DRV_NAME, ret);
> > +               return -ENODEV;
> > +       }
> > +
> > +       dev_set_parent_plat(child_dev, dev_get_plat(dev));
> > +
> > +       return 0;
> > +}
> > +
> > +static const struct udevice_id sandbox_ffa_id[] = {
> > +       { "sandbox,arm_ffa", 0 },
> > +       { },
> > +};
> > +
> > +/* Declaring the sandbox_arm_ffa driver under UCLASS_FFA */
> > +U_BOOT_DRIVER(sandbox_arm_ffa) = {
> > +       .name           = FFA_SANDBOX_DRV_NAME,
> > +       .of_match = sandbox_ffa_id,
> > +       .id             = UCLASS_FFA,
> > +       .probe          = sandbox_ffa_probe,
> > +       .priv_auto      = sizeof(struct sandbox_ffa_priv),
> > +};
> > diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> > new file mode 100644
> > index 0000000000..c35d80de16
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> > @@ -0,0 +1,129 @@
> > +/* 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 <sandbox_arm_ffa.h>
> > +#include "arm_ffa_priv.h"
> > +
> > +/* This header is exclusively used by the Sandbox FF-A driver and sandbox tests */
> > +
> > +/* 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
> 
> It's a convention to put negative values in brackets just in case of
> operator-precedence issues. Or you could use an enum.
> 
> > +
> > +/* 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 secure partitions emulated by the FF-A sandbox driver */
> > +#define SANDBOX_PARTITIONS_CNT (4)
> > +
> > +/* Binary data of services UUIDs emulated by the FF-A sandbox driver */
> > +
> > +/* 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_priv - 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_priv {
> > +       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(struct udevice *dev, \
> > +                                                             ffa_value_t *pargs, ffa_value_t *res)
> 
> drop that
> 
> [..]
> 
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v9 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-03-10 20:50                                                                                       ` Simon Glass
@ 2023-03-14 17:05                                                                                         ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-14 17:05 UTC (permalink / raw)
  To: Simon Glass; +Cc: ilias.apalodimas, achin.gupta, xueliang.zhong, nd, u-boot

On Fri, Mar 10, 2023 at 12:50:01PM -0800, Simon Glass wrote:

Hi Simon,

> Hi Abdellatif,
> 
> On Fri, 10 Mar 2023 at 06:11, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > Add MM communication support using FF-A transport
> >
> > This feature allows accessing MM partitions services through
> > EFI MM communication protocol. MM partitions such as StandAlonneMM
> > or smm-gateway secure partitions which reside in secure world.
> >
> > An MM shared buffer and a door bell event are used to exchange
> > the data.
> >
> > The data is used by EFI services such as GetVariable()/SetVariable()
> > and copied from the communication buffer to the MM shared buffer.
> >
> > The secure partition is notified about availability of data in the
> > MM shared buffer by an FF-A message (door bell).
> >
> > On such event, MM SP can read the data and updates the MM shared
> > buffer with the response data.
> >
> > The response data is copied back to the communication buffer and
> > consumed by the EFI subsystem.
> >
> > MM communication protocol supports FF-A 64-bit direct messaging.
> >
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>
> >
> > ---
> > Changelog:
> > ===============
> >
> > v9: align how FF-A is used with FF-A discovery through DM
> >
> > v8:
> >
> > * isolate the compilation choices between FF-A and OP-TEE
> > * update partition_info_get() second argument to be an SP count
> > * pass NULL device pointer to the FF-A bus discovery and operations
> >
> > v7:
> >
> > * set the MM door bell event to use 64-bit direct messaging
> > * issue a compile time error when one of these macros are not found :
> >   FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
> > * make mm_sp_svc_uuid static
> > * replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
> > * improve use of unmap_sysmem() in ffa_mm_communicate()
> >
> > v6:
> >
> > * add FF-A runtime discovery at MM communication level
> > * drop EFI runtime support for FF-A MM communication
> > * revert the changes in include/mm_communication.h for
> >   efi_mm_communicate_header and smm_variable_access structures
> >
> > v4:
> >
> > * use the new FF-A driver interfaces
> > * discover MM partitions at runtime
> > * copy FF-A driver private data to EFI runtime section at
> >   ExitBootServices()
> > * drop use of FFA_ERR_STAT_SUCCESS error code
> > * replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
> >   in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
> > * revert the error log in mm_communicate() in case of failure
> > * remove packed attribute from efi_mm_communicate_header and
> >   smm_variable_communicate_header
> >
> > v2:
> >
> > * set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings
> >
> > v1:
> >
> > * introduce FF-A MM communication
> >
> >  include/mm_communication.h        |   6 +
> >  lib/efi_loader/Kconfig            |  14 +-
> >  lib/efi_loader/efi_variable_tee.c | 317 +++++++++++++++++++++++++++++-
> >  3 files changed, 331 insertions(+), 6 deletions(-)
> >
> > diff --git a/include/mm_communication.h b/include/mm_communication.h
> > index e65fbde60d..87509fec3f 100644
> > --- a/include/mm_communication.h
> > +++ b/include/mm_communication.h
> > @@ -6,6 +6,9 @@
> >   *  Copyright (c) 2017, Intel Corporation. All rights reserved.
> >   *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
> >   *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
> > + *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> > + *    Authors:
> > + *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >
> >  #ifndef _MM_COMMUNICATION_H_
> > @@ -13,6 +16,9 @@
> >
> >  #include <part_efi.h>
> >
> > +/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
> > +#define MM_SP_UUID     "33d532ed-e699-0942-c09c-a798d9cd722d"
> > +
> >  /*
> >   * Interface to the pseudo Trusted Application (TA), which provides a
> >   * communication channel with the Standalone MM (Management Mode)
> > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > index c5835e6ef6..08a6b84101 100644
> > --- a/lib/efi_loader/Kconfig
> > +++ b/lib/efi_loader/Kconfig
> > @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
> >           stored as file /ubootefi.var on the EFI system partition.
> >
> >  config EFI_MM_COMM_TEE
> > -       bool "UEFI variables storage service via OP-TEE"
> > -       depends on OPTEE
> > +       bool "UEFI variables storage service via the trusted world"
> > +       depends on OPTEE || ARM_FFA_TRANSPORT
> >         help
> > +         Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
> > +         When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> > +         When using the u-boot FF-A  driver any MM SP is supported.
> > +
> >           If OP-TEE is present and running StandAloneMM, dispatch all UEFI
> >           variable related operations to that. The application will verify,
> >           authenticate and store the variables on an RPMB.
> >
> > +         When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> > +         operations to the MM SP running in the secure world.
> > +         A door bell mechanism is used to notify the SP when there is data in the shared
> > +         MM buffer. The data is copied by u-boot to the shared buffer before issuing
> > +         the door bell event.
> > +
> >  config EFI_VARIABLE_NO_STORE
> >         bool "Don't persist non-volatile UEFI variables"
> >         help
> > diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> > index dfef18435d..86207f1ff2 100644
> > --- a/lib/efi_loader/efi_variable_tee.c
> > +++ b/lib/efi_loader/efi_variable_tee.c
> > @@ -4,9 +4,14 @@
> >   *
> >   *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
> >   *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
> > + *  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 <efi.h>
> >  #include <efi_api.h>
> >  #include <efi_loader.h>
> > @@ -15,6 +20,36 @@
> >  #include <malloc.h>
> >  #include <mm_communication.h>
> >
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> 
> Please avoid excluding code unless you need to

All FF-A code in this file needs to be excluded from the build when FF-A is off.
IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) is needed.

Ilias could provide more details about the Optee ifdefs (which are needed as well).

> 
> > +
> > +#include <arm_ffa.h>
> > +#include <cpu_func.h>
> > +#include <mapmem.h>
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> > +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_SIZE 0
> 
> Shouldn't that info be in the DT?

The shared MM buffer is a software feature and belongs to the MM protocol (a higher level than FF-A).
It doesn't make sense to describe this in the DT.

> 
> > +#endif
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_OFFSET
> > +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_OFFSET 0
> > +#endif
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> > +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_ADDR 0
> > +#endif
> > +
> > +/* MM return codes */
> > +#define MM_SUCCESS (0)
> > +
> > +static const char *mm_sp_svc_uuid = MM_SP_UUID;
> > +
> > +static u16 mm_sp_id;
> > +
> > +#endif
> > +
> >  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
> >  static efi_uintn_t max_buffer_size;    /* comm + var + func + data */
> >  static efi_uintn_t max_payload_size;   /* func + data */
> > @@ -24,6 +59,7 @@ struct mm_connection {
> >         u32 session;
> >  };
> >
> > +#if (IS_ENABLED(CONFIG_OPTEE))
> 
> same here

Optee code in this file is only valid when CONFIG_OPTEE is turned on.
We don't need to compile a code that's not used.

> 
> >  /**
> >   * get_connection() - Retrieve OP-TEE session for a specific UUID.
> >   *
> > @@ -143,13 +179,269 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
> >
> >         return ret;
> >  }
> > +#endif
> > +
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> 
> and here
> 
> > +
> > +/**
> > + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> > + *
> > + * Notifies the MM partition in the trusted world that
> > + * data is available in the shared buffer.
> > + * This is a blocking call during which trusted world has exclusive access
> > + * to the MM shared buffer.
> > + *
> > + * Return:
> > + *
> > + * 0 on success
> > + */
> > +static int ffa_notify_mm_sp(void)
> > +{
> > +       struct ffa_send_direct_data msg = {0};
> > +       int ret;
> > +       int sp_event_ret = -1;
> > +       struct udevice *ffa_dev = NULL;
> > +       struct ffa_bus_ops *ffa_ops = NULL;
> > +
> > +       uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev);
> 
> uclass_first_device()
> 
> > +       if (!ffa_dev) {
> > +               log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev);
> > +       if (!ffa_ops) {
> > +               log_err("EFI: Invalid FF-A ops, notify MM SP failure\n");
> > +               return -EINVAL;
> > +       }
> > +
> > +       msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
> > +
> > +       ret = ffa_ops->sync_send_receive(ffa_dev, mm_sp_id, &msg, 1);
> > +       if (ret != 0)
> > +               return ret;
> > +
> > +       sp_event_ret = msg.data0; /* x3 */
> > +
> > +       if (sp_event_ret == MM_SUCCESS)
> > +               return 0;
> > +
> > +       /*
> > +        * Failure to notify the MM SP
> > +        */
> 
> /* Failure ... */
> 
> > +
> > +       return -EACCES;
> > +}
> > +
> > +/**
> > + * ffa_discover_mm_sp_id() - Query the MM partition ID
> > + *
> > + * Use the FF-A driver to get the MM partition ID.
> > + * If multiple partitions are found, use the first one.
> > + * This is a boot time function.
> > + *
> > + * Return:
> > + *
> > + * 0 on success
> > + */
> > +static int ffa_discover_mm_sp_id(void)
> > +{
> > +       u32 count = 0;
> > +       int ret;
> > +       struct ffa_partition_info *parts_info;
> > +       struct udevice *ffa_dev = NULL;
> > +       struct ffa_bus_ops *ffa_ops = NULL;
> > +
> > +       uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev);
> > +       if (!ffa_dev) {
> > +               log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev);
> > +       if (!ffa_ops) {
> > +               log_err("EFI: Invalid FF-A ops, MM SP discovery failure\n");
> > +               return -EINVAL;
> > +       }
> > +
> > +       /* Get from the driver the count of the SPs matching the UUID */
> > +       ret = ffa_ops->partition_info_get(ffa_dev, mm_sp_svc_uuid, &count, NULL);
> > +       if (ret != 0) {
> > +               log_err("EFI: Failure in querying SPs count (%d), MM SP discovery failure\n", ret);
> > +               return ret;
> > +       }
> > +
> > +       if (!count) {
> > +               log_info("EFI: No MM partition found\n");
> > +               return ret;
> > +       }
> > +
> > +       /* Pre-allocate a buffer to be filled by the driver with ffa_partition_info structs */
> > +
> > +       log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
> > +
> > +       parts_info = calloc(count, sizeof(*parts_info));
> > +       if (!parts_info)
> > +               return -ENOMEM;
> > +
> > +       /* Ask the driver to fill the buffer with the SPs info */
> > +       ret = ffa_ops->partition_info_get(ffa_dev, mm_sp_svc_uuid, &count, parts_info);
> > +       if (ret) {
> > +               log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
> > +               free(parts_info);
> > +               return ret;
> > +       }
> > +
> > +       /* MM SPs found , use the first one */
> > +
> > +       mm_sp_id = parts_info[0].id;
> > +
> > +       log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
> > +
> > +       free(parts_info);
> > +
> > +       return 0;
> > +}
> > +
> > +/**
> > + * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
> > + * @comm_buf:          locally allocated communication buffer used for rx/tx
> > + * @dsize:                             communication buffer size
> > + *
> > + * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
> > + * that there is data to read from the shared buffer.
> > + * Communication with the MM SP is performed using FF-A transport.
> > + * On the event, MM SP can read the data from the buffer and
> > + * update the MM shared buffer with response data.
> > + * The response data is copied back to the communication buffer.
> > + *
> > + * Return:
> > + *
> > + * EFI status code
> > + */
> > +static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
> > +{
> > +       ulong tx_data_size;
> > +       int ffa_ret;
> > +       efi_status_t efi_ret;
> > +       struct efi_mm_communicate_header *mm_hdr;
> > +       void *virt_shared_buf;
> > +
> > +       if (!comm_buf)
> > +               return EFI_INVALID_PARAMETER;
> > +
> > +       /* Discover MM partition ID at boot time */
> > +       if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
> > +               log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
> > +               return EFI_UNSUPPORTED;
> > +       }
> > +
> > +       mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> > +       tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
> > +
> > +       if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
> > +               return EFI_INVALID_PARAMETER;
> > +
> > +       /* Copy the data to the shared buffer */
> > +
> > +       virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
> > +       memcpy(virt_shared_buf, comm_buf, tx_data_size);
> > +
> > +       /*
> > +        * The secure world might have cache disabled for
> > +        * the device region used for shared buffer (which is the case for Optee).
> > +        * In this case, the secure world reads the data from DRAM.
> > +        * Let's flush the cache so the DRAM is updated with the latest data.
> > +        */
> > +       #ifdef CONFIG_ARM64
> > +       invalidate_dcache_all();
> 
> indent, I think?
> 
> > +       #endif
> > +
> > +       /* Announce there is data in the shared buffer */
> > +
> > +       ffa_ret = ffa_notify_mm_sp();
> > +
> > +       switch (ffa_ret) {
> > +       case 0:
> > +       {
> 
> Don't we normally put the { at the end of the previous line?
> 
> 
> > +               ulong rx_data_size;
> > +               /* Copy the MM SP response from the shared buffer to the communication buffer */
> > +               rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> > +                       sizeof(efi_guid_t) +
> > +                       sizeof(size_t);
> > +
> > +               if (rx_data_size > comm_buf_size) {
> > +                       efi_ret = EFI_OUT_OF_RESOURCES;
> > +                       break;
> > +               }
> > +
> > +               memcpy(comm_buf, virt_shared_buf, rx_data_size);
> > +               efi_ret = EFI_SUCCESS;
> > +               break;
> > +       }
> > +       case -EINVAL:
> > +               efi_ret = EFI_DEVICE_ERROR;
> > +               break;
> > +       case -EPERM:
> > +               efi_ret = EFI_INVALID_PARAMETER;
> > +               break;
> > +       case -EACCES:
> > +               efi_ret = EFI_ACCESS_DENIED;
> > +               break;
> > +       case -EBUSY:
> > +               efi_ret = EFI_OUT_OF_RESOURCES;
> > +               break;
> > +       default:
> > +               efi_ret = EFI_ACCESS_DENIED;
> > +       }
> > +
> > +       unmap_sysmem(virt_shared_buf);
> > +       return efi_ret;
> > +}
> > +#endif
> > +
> > +/**
> > + * select_ffa_mm_comms() - checks FF-A support availability
> > + *
> > + * Making sure FF-A is compiled in. If that's the case try to make sure
> > + * the FF-A bus is probed successfully which means FF-A communication
> > + * with secure world works and ready to be used.
> > + *
> > + * Return:
> > + *
> > + * 0: FF-A ready for use. Otherwise, failure
> > + */
> > +static efi_status_t select_ffa_mm_comms(void)
> > +{
> > +       efi_status_t ret = EFI_UNSUPPORTED;
> > +
> > +       if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) {
> > +               struct udevice *dev = NULL;
> > +
> > +               uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &dev);
> > +               if (!dev) {
> > +                       log_err("EFI: Cannot find FF-A bus device, cannot select FF-A comms\n");
> > +                       ret = EFI_NOT_READY;
> > +               } else {
> > +                       ret = EFI_SUCCESS;
> > +               }
> > +       }
> > +
> > +       return ret;
> > +}
> >
> >  /**
> > - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
> speeding
> 
> > + * mm_communicate() - Adjust the communication buffer to the MM SP and send
> >   * it to OP-TEE
> >   *
> > - * @comm_buf:          locally allocted communcation buffer
> 
> spelling
> 
> > + * @comm_buf:          locally allocated communication buffer
> >   * @dsize:             buffer size
> > + *
> > + * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
> > + * The comm_buf format is the same for both partitions.
> > + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> > + * When using the u-boot FF-A  driver, any MM SP is supported.
> > + *
> >   * Return:             status code
> >   */
> >  static efi_status_t (u8 *comm_buf, efi_uintn_t dsize)
> > @@ -162,7 +454,17 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> >         mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> >         var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
> 
> smm_var_comms_hdr would be a lot shorter!

Sorry, it's beyond the scope of the FF-A patchset. The FF-A patchset is not providing
the smm_variable_communicate_header structure.

> 
> 
> >
> > -       ret = optee_mm_communicate(comm_buf, dsize);
> > +       ret = select_ffa_mm_comms();
> > +       if (ret != EFI_SUCCESS) {
> > +#if (IS_ENABLED(CONFIG_OPTEE))
> > +               ret = optee_mm_communicate(comm_buf, dsize);
> > +#endif
> > +       } else {
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +               ret = ffa_mm_communicate(comm_buf, dsize);
> > +#endif
> > +       }
> > +
> >         if (ret != EFI_SUCCESS) {
> >                 log_err("%s failed!\n", __func__);
> >                 return ret;
> > @@ -258,6 +560,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
> >                 goto out;
> >         }
> >         *size = var_payload->size;
> > +
> > +       #if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +               if (*size > FFA_SHARED_MM_BUFFER_SIZE)
> > +                       *size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE  -
> > +                               MM_VARIABLE_COMMUNICATE_SIZE;
> > +       #endif
> > +
> >         /*
> >          * There seems to be a bug in EDK2 miscalculating the boundaries and
> >          * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> > @@ -697,7 +1006,7 @@ void efi_variables_boot_exit_notify(void)
> >                 ret = EFI_NOT_FOUND;
> >
> >         if (ret != EFI_SUCCESS)
> > -               log_err("Unable to notify StMM for ExitBootServices\n");
> > +               log_err("Unable to notify the MM partition for ExitBootServices\n");
> >         free(comm_buf);
> >
> >         /*
> > --
> > 2.25.1
> >
> 
> Regards,
> Simonn

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v9 06/10] arm_ffa: introduce the FF-A Sandbox driver
  2023-03-10 20:49                                                                                       ` Simon Glass
  2023-03-14 12:55                                                                                         ` Abdellatif El Khlifi
@ 2023-03-14 17:59                                                                                         ` Abdellatif El Khlifi
  2023-03-15 14:05                                                                                           ` Simon Glass
  1 sibling, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-14 17:59 UTC (permalink / raw)
  To: Simon Glass; +Cc: xueliang.zhong, nd, u-boot

Hi Simon,

> Hi Abdellatif,
> 
> On Fri, 10 Mar 2023 at 06:10, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > 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>
> >
> > ---
> > Changelog:
> > ===============
> >
> > v9: align FF-A sandbox driver with FF-A discovery through DM
> >
> > v8: update ffa_bus_prvdata_get() to return a pointer rather than
> >     a pointer address
> >
> > v7: state that sandbox driver supports only 64-bit direct messaging
> >
> > v4: align sandbox driver with the new FF-A driver interfaces
> >     and new way of error handling
> >
> > v1: introduce the sandbox driver
> >
> >  MAINTAINERS                                   |   1 +
> >  arch/sandbox/dts/sandbox.dtsi                 |   4 +
> >  arch/sandbox/dts/test.dts                     |   4 +
> >  configs/sandbox64_defconfig                   |   2 +
> >  configs/sandbox_defconfig                     |   2 +
> >  doc/arch/arm64.ffa.rst                        |   4 +
> >  doc/arch/sandbox/sandbox.rst                  |   1 +
> >  drivers/firmware/arm-ffa/Kconfig              |  11 +-
> >  drivers/firmware/arm-ffa/Makefile             |   1 +
> >  drivers/firmware/arm-ffa/core.c               |  36 +-
> >  drivers/firmware/arm-ffa/sandbox.c            | 610 ++++++++++++++++++
> >  .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   | 129 ++++
> >  include/arm_ffa.h                             |   5 +-
> >  include/sandbox_arm_ffa.h                     | 124 ++++
> >  14 files changed, 928 insertions(+), 6 deletions(-)
> >  create mode 100644 drivers/firmware/arm-ffa/sandbox.c
> >  create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> >  create mode 100644 include/sandbox_arm_ffa.h
> >
> 
> Could you use 80 columns where possible? There seem to be a lot of
> things that extend beyond that without much of a reason.
> 
> Also you can use 'ulong' instead of 'unsigned long'. It is less
> verbose and a U-Boot standard.
> 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 18e9c2ce99..2b9d33e964 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -274,6 +274,7 @@ 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..059c273277 100644
> > --- a/arch/sandbox/dts/sandbox.dtsi
> > +++ b/arch/sandbox/dts/sandbox.dtsi
> > @@ -445,6 +445,10 @@
> >         thermal {
> >                 compatible = "sandbox,thermal";
> >         };
> > +
> > +       sandbox_arm_ffa {
> > +               compatible = "sandbox,arm_ffa";
> > +       };
> >  };
> >
> >  &cros_ec {
> > diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> > index d72d7a567a..11dc6ed0d9 100644
> > --- a/arch/sandbox/dts/test.dts
> > +++ b/arch/sandbox/dts/test.dts
> > @@ -1802,6 +1802,10 @@
> >                 compatible = "u-boot,fwu-mdata-gpt";
> >                 fwu-mdata-store = <&mmc0>;
> >         };
> > +
> > +       sandbox_arm_ffa {
> > +               compatible = "sandbox,arm_ffa";
> > +       };
> 
> I see that you have this, so the driver should bind automatically.
> 
> Is the problem that you are trying to bind the sandbox emulator?
> Again, you can actually add that to the DT. See how this works for
> i2c, SPI, PCI, for example.
> 
> >  };
> >
> >  #include "sandbox_pmic.dtsi"
> > diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
> > index ccbc18aad0..35d4676cf7 100644
> > --- a/configs/sandbox64_defconfig
> > +++ b/configs/sandbox64_defconfig
> > @@ -259,3 +259,5 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
> >  CONFIG_UNIT_TEST=y
> >  CONFIG_UT_TIME=y
> >  CONFIG_UT_DM=y
> > +CONFIG_ARM_FFA_TRANSPORT=y
> > +CONFIG_SANDBOX_FFA=y
> > diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
> > index a0fbdad20a..8aab8dda31 100644
> > --- a/configs/sandbox_defconfig
> > +++ b/configs/sandbox_defconfig
> > @@ -336,3 +336,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/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> > index 8fad9ef3d0..555ee9a6ae 100644
> > --- a/doc/arch/arm64.ffa.rst
> > +++ b/doc/arch/arm64.ffa.rst
> > @@ -64,6 +64,10 @@ CONFIG_ARM_FFA_TRANSPORT
> >      Enables the FF-A bus driver. Turn this on if you want to use FF-A
> >      communication.
> >
> > +CONFIG_SANDBOX_FFA
> > +    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
> > +    Sandbox and provides functional tests for FF-A.
> 
> OK that is why I am confused. Please don't call this a driver. It is
> an emulator. When you have an emulator and a driver for the same thing
> it gets confusing.
> 
> > +
> >  FF-A ABIs under the hood
> >  ---------------------------------------
> >
> > diff --git a/doc/arch/sandbox/sandbox.rst b/doc/arch/sandbox/sandbox.rst
> > index cd7f8a2cb0..c5df372e00 100644
> > --- a/doc/arch/sandbox/sandbox.rst
> > +++ b/doc/arch/sandbox/sandbox.rst
> > @@ -200,6 +200,7 @@ Supported Drivers
> >
> >  U-Boot sandbox supports these emulations:
> >
> > +- Arm FF-A
> >  - Block devices
> >  - Chrome OS EC
> >  - GPIO
> > diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> > index 2cfd7ef5fc..b5430eb6f4 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
> > @@ -32,3 +32,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 c8d83b4bc9..d22c1ba609 100644
> > --- a/drivers/firmware/arm-ffa/Makefile
> > +++ b/drivers/firmware/arm-ffa/Makefile
> > @@ -6,3 +6,4 @@
> >  #   Abdellatif El Khlifi <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/core.c b/drivers/firmware/arm-ffa/core.c
> > index 2210f5343c..0d2e6ff0d4 100644
> > --- a/drivers/firmware/arm-ffa/core.c
> > +++ b/drivers/firmware/arm-ffa/core.c
> > @@ -1042,6 +1042,7 @@ bool ffa_try_discovery(void)
> >         return true;
> >  }
> >
> > +#if !CONFIG_IS_ENABLED(SANDBOX_FFA)
> 
> We should not need #ifdefs here. The sandbox driver is just another
> driver, just like there is the ARM driver. We select the correct one
> using the devicetree and everything just works.

The FF-A core driver (core.c) has Arm specific code that is not available
when running sandbox. So we still need to use these ifdefs in core.c
to prevent the Arm specific code from building under sandbox.
For example these are Arm specific:

arm_smccc_1_2_smc()
struct arm_smccc_res 
ARM_SMCCC_FEATURE_DRIVER
The SMC conduit. In sandbox mode the core driver should use the emulated conduit implemented by sandbox_arm_ffa_smccc_smc()

> 
> >  /**
> >   * __arm_ffa_fn_smc() - SMC wrapper
> >   * @args: FF-A ABI arguments to be copied to Xn registers
> > @@ -1069,6 +1070,7 @@ void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
> >   * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
> >   * So, the legacy SMC invocation is not used.
> >   *
> > + * In Sandbox mode sandbox_arm_ffa is used to test arm_ffa driver.
> >   * Return:
> >   *
> >   * 0 on success. Otherwise, failure
> > @@ -1088,6 +1090,30 @@ ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
> >         .driver_name = FFA_DRV_NAME,
> >         .is_supported = ffa_bus_is_supported,
> >  };
> > +#else
> > +/* SANDBOX_FFA */
> > +
> > +/**
> > + * ffa_bind() - The driver bind function
> > + * @dev:       the arm_ffa device
> > + * When using sandbox tries to discover the emulated FF-A bus.
> > + * Return:
> > + *
> > + * 0 on success.
> > + */
> > +static int ffa_bind(struct udevice *dev)
> 
> I don't think this is binding anything. How about ffa_get_dev() ?

In sandbox mode, when the FF-A sandbox driver (emulates the secure world) is probed,  it calls
device_bind_driver() to bind the FF-A core driver (a similar approach to the PSCI way).
ffa_bind() is needed in sandbox mode so the FF-A discovery is setup properly.

In an Arm platform, the PSCI driver calls the FF-A discovery callback
ffa_bus_is_supported() which tries to discover FF-A. When discovery is successful,
PSCI driver binds the FF-A core device by calling device_bind_driver()

The core driver needs to work on both Arm and sandbox.
The sandbox FF-A driver plays the role of a secure world emulator with which
the FF-A core driver exchanges data.

> 
> > +{
> > +       bool ret;
> > +
> > +       log_info("[FFA] binding the device\n");
> > +
> > +       ret = ffa_try_discovery();
> > +       if (ret)
> > +               return 0;
> > +       else
> > +               return -ENODEV;
> > +}
> > +#endif
> >
> >  /**
> >   * ffa_set_smc_conduit() - Set the SMC conduit
> > @@ -1101,7 +1127,12 @@ ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
> >   */
> >  static int ffa_set_smc_conduit(void)
> >  {
> > -       dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc;
> > +#if CONFIG_IS_ENABLED(SANDBOX_FFA)
> > +               dscvry_info.invoke_ffa_fn = sandbox_arm_ffa_smccc_smc;
> > +               log_info("[FFA] Using SMC emulation\n");
> > +#else
> > +               dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc;
> > +#endif
> 
> This needs to be reworked to go through the uclass to the correct
> driver. Basically you need an ARM driver and a sandbox driver (which
> attaches to the emulator).
> 
> There should not be #idefs in this sort of code...driver model should
> handle it. See other uclasses for examples.

In sandbox we are testing the FF-A core driver. The core driver has some Arm specific code which
explains why we need the ifdefs. In Arm the SMC conduit is implemented by __arm_ffa_fn_smc()
which ends up calling Arm instructions.
When building the core driver with sandbox, the SMC conduit is set to the emulated version of the SMC calls
implemented by sandbox_arm_ffa_smccc_smc()

I'm happy to rename the FF-A sandbox driver to the FF-A sandbox emulator if that clears the doubts.
However, the emulator is still a driver and bound to a sandbox device (the parent of the core).

Cheers,
Abdellatif

> 
> >
> >         log_info("[FFA] Conduit is SMC\n");
> >
> > @@ -1246,4 +1277,7 @@ U_BOOT_DRIVER(arm_ffa) = {
> >         .remove = ffa_remove,
> >         .unbind = ffa_unbind,
> >         .ops            = &ffa_ops,
> > +#if CONFIG_IS_ENABLED(SANDBOX_FFA)
> > +       .bind           = ffa_bind,
> 
> Can drop this
> 
> > +#endif
> >  };
> > diff --git a/drivers/firmware/arm-ffa/sandbox.c b/drivers/firmware/arm-ffa/sandbox.c
> 
> sandbox_emul.c pehaps?
> 
> I am pretty sure this is an emulator
> 
> > new file mode 100644
> > index 0000000000..84c2fc929f
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/sandbox.c
> > @@ -0,0 +1,610 @@
> > +// 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 <dm/device-internal.h>
> > +#include <dm/lists.h>
> > +#include <dm/root.h>
> > +#include <linux/errno.h>
> > +#include <linux/sizes.h>
> > +#include "sandbox_arm_ffa_priv.h"
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/* The partitions (SPs) table */
> > +static struct ffa_partition_desc sandbox_partitions[SANDBOX_PARTITIONS_CNT] = {
> > +       {
> > +               .info = { .id = SANDBOX_SP1_ID, .exec_ctxt = 0x5687, .properties = 0x89325621 },
> > +               .sp_uuid = {
> > +                       .a1 = SANDBOX_SERVICE1_UUID_A1,
> > +                       .a2 = SANDBOX_SERVICE1_UUID_A2,
> > +                       .a3 = SANDBOX_SERVICE1_UUID_A3,
> > +                       .a4 = SANDBOX_SERVICE1_UUID_A4,
> > +               }
> > +       },
> > +       {
> > +               .info = { .id = SANDBOX_SP2_ID, .exec_ctxt = 0x9587, .properties = 0x45325621 },
> > +               .sp_uuid = {
> > +                       .a1 = SANDBOX_SERVICE2_UUID_A1,
> > +                       .a2 = SANDBOX_SERVICE2_UUID_A2,
> > +                       .a3 = SANDBOX_SERVICE2_UUID_A3,
> > +                       .a4 = SANDBOX_SERVICE2_UUID_A4,
> > +               }
> > +       },
> > +       {
> > +               .info = { .id = SANDBOX_SP3_ID, .exec_ctxt = 0x7687, .properties = 0x23325621 },
> > +               .sp_uuid = {
> > +                       .a1 = SANDBOX_SERVICE1_UUID_A1,
> > +                       .a2 = SANDBOX_SERVICE1_UUID_A2,
> > +                       .a3 = SANDBOX_SERVICE1_UUID_A3,
> > +                       .a4 = SANDBOX_SERVICE1_UUID_A4,
> > +               }
> > +       },
> > +       {
> > +               .info = { .id = SANDBOX_SP4_ID, .exec_ctxt = 0x1487, .properties = 0x70325621 },
> > +               .sp_uuid = {
> > +                       .a1 = SANDBOX_SERVICE2_UUID_A1,
> > +                       .a2 = SANDBOX_SERVICE2_UUID_A2,
> > +                       .a3 = SANDBOX_SERVICE2_UUID_A3,
> > +                       .a4 = SANDBOX_SERVICE2_UUID_A4,
> > +               }
> > +       }
> > +
> > +};
> > +
> > +/* Driver functions */
> > +
> > +/**
> > + * sandbox_ffa_version() - Emulated FFA_VERSION handler function
> > + * @dev:       the sandbox FF-A device
> > + * @{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)
> 
> Instead of the macro can you write this out in full? It defeats ctags, etc.
> 
> > +{
> > +       struct sandbox_ffa_priv *priv = dev_get_priv(dev);
> > +
> > +       priv->fwk_version = FFA_VERSION_1_0;
> > +       res->a0 = priv->fwk_version;
> 
> Where is res defined?
> 
> > +
> > +       /* 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
> > + * @dev:       the sandbox FF-A device
> > + * @{a0-a7} , res: The SMC call arguments and return structure.
> > + *
> > + * This is the function that emulates FFA_ID_GET FF-A function.
> 
> s/This is the function that e/E/g
> 
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +SANDBOX_SMC_FFA_ABI(ffa_id_get)
> > +{
> > +       struct sandbox_ffa_priv *priv = dev_get_priv(dev);
> > +
> > +       res->a0 = FFA_SMC_32(FFA_SUCCESS);
> > +       res->a1 = 0;
> > +
> > +       priv->id = NS_PHYS_ENDPOINT_ID;
> > +       res->a2 = priv->id;
> > +
> > +       /* x3-x7 MBZ */
> > +       memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long));
> > +
> > +       return 0;
> > +}
> > +
> > +/**
> > + * sandbox_ffa_features() - Emulated FFA_FEATURES handler function
> > + * @dev:       the sandbox FF-A device
> > + * @{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));
> > +               log_err("[FFA] [Sandbox] FF-A interface 0x%lx not implemented\n", pargs->a1);
> 
> return -ENOSYS
> 
> > +       }
> > +
> > +       res->a1 = 0;
> > +
> > +       return 0;
> > +}
> > +
> 
> [..]
> 
> > +SANDBOX_SMC_FFA_ABI(ffa_msg_send_direct_req)
> > +{
> > +       u16 part_id;
> > +       struct sandbox_ffa_priv *priv = dev_get_priv(dev);
> > +
> > +       part_id = GET_DST_SP_ID(pargs->a1);
> > +
> > +       if ((GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id) ||
> 
> drop extra brackets
> 
> > +           !sandbox_ffa_sp_valid(dev, 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(priv->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;
> 
> Would -1UL work?
> 
> > +
> > +       return 0;
> > +}
> > +
> 
> [..]
> 
> > +static int sandbox_ffa_probe(struct udevice *dev)
> > +{
> > +       struct udevice *child_dev = NULL;
> > +       int ret;
> > +
> > +       ret = device_bind_driver(dev, FFA_DRV_NAME, FFA_DRV_NAME, &child_dev);
> 
> Is this binding the emulator? Add it to the DT instead.
> 
> If you put
> 
> .post_bind = dm_scan_fdt_dev()
> 
> in your uclass (like spi-uclass.c does) then it will binding
> child-node devices automatically. Then you can make your emulator a
> child node.
> 
> > +       if (ret) {
> > +               pr_err("%s was not bound: %d, aborting\n", FFA_DRV_NAME, ret);
> > +               return -ENODEV;
> > +       }
> > +
> > +       dev_set_parent_plat(child_dev, dev_get_plat(dev));
> > +
> > +       return 0;
> > +}
> > +
> > +static const struct udevice_id sandbox_ffa_id[] = {
> > +       { "sandbox,arm_ffa", 0 },
> > +       { },
> > +};
> > +
> > +/* Declaring the sandbox_arm_ffa driver under UCLASS_FFA */
> > +U_BOOT_DRIVER(sandbox_arm_ffa) = {
> > +       .name           = FFA_SANDBOX_DRV_NAME,
> > +       .of_match = sandbox_ffa_id,
> > +       .id             = UCLASS_FFA,
> > +       .probe          = sandbox_ffa_probe,
> > +       .priv_auto      = sizeof(struct sandbox_ffa_priv),
> > +};
> > diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> > new file mode 100644
> > index 0000000000..c35d80de16
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> > @@ -0,0 +1,129 @@
> > +/* 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 <sandbox_arm_ffa.h>
> > +#include "arm_ffa_priv.h"
> > +
> > +/* This header is exclusively used by the Sandbox FF-A driver and sandbox tests */
> > +
> > +/* 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
> 
> It's a convention to put negative values in brackets just in case of
> operator-precedence issues. Or you could use an enum.
> 
> > +
> > +/* 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 secure partitions emulated by the FF-A sandbox driver */
> > +#define SANDBOX_PARTITIONS_CNT (4)
> > +
> > +/* Binary data of services UUIDs emulated by the FF-A sandbox driver */
> > +
> > +/* 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_priv - 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_priv {
> > +       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(struct udevice *dev, \
> > +                                                             ffa_value_t *pargs, ffa_value_t *res)
> 
> drop that
> 
> [..]
> 
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v9 06/10] arm_ffa: introduce the FF-A Sandbox driver
  2023-03-14 17:59                                                                                         ` Abdellatif El Khlifi
@ 2023-03-15 14:05                                                                                           ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-03-15 14:05 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: xueliang.zhong, nd, u-boot

Hi Abdellatif,

On Tue, 14 Mar 2023 at 11:59, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Hi Simon,
>
> > Hi Abdellatif,
> >
> > On Fri, 10 Mar 2023 at 06:10, Abdellatif El Khlifi
> > <abdellatif.elkhlifi@arm.com> wrote:
> > >
> > > 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>
> > >
> > > ---
> > > Changelog:
> > > ===============
> > >
> > > v9: align FF-A sandbox driver with FF-A discovery through DM
> > >
> > > v8: update ffa_bus_prvdata_get() to return a pointer rather than
> > >     a pointer address
> > >
> > > v7: state that sandbox driver supports only 64-bit direct messaging
> > >
> > > v4: align sandbox driver with the new FF-A driver interfaces
> > >     and new way of error handling
> > >
> > > v1: introduce the sandbox driver
> > >
> > >  MAINTAINERS                                   |   1 +
> > >  arch/sandbox/dts/sandbox.dtsi                 |   4 +
> > >  arch/sandbox/dts/test.dts                     |   4 +
> > >  configs/sandbox64_defconfig                   |   2 +
> > >  configs/sandbox_defconfig                     |   2 +
> > >  doc/arch/arm64.ffa.rst                        |   4 +
> > >  doc/arch/sandbox/sandbox.rst                  |   1 +
> > >  drivers/firmware/arm-ffa/Kconfig              |  11 +-
> > >  drivers/firmware/arm-ffa/Makefile             |   1 +
> > >  drivers/firmware/arm-ffa/core.c               |  36 +-
> > >  drivers/firmware/arm-ffa/sandbox.c            | 610 ++++++++++++++++++
> > >  .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   | 129 ++++
> > >  include/arm_ffa.h                             |   5 +-
> > >  include/sandbox_arm_ffa.h                     | 124 ++++
> > >  14 files changed, 928 insertions(+), 6 deletions(-)
> > >  create mode 100644 drivers/firmware/arm-ffa/sandbox.c
> > >  create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> > >  create mode 100644 include/sandbox_arm_ffa.h
> > >
> >
> > Could you use 80 columns where possible? There seem to be a lot of
> > things that extend beyond that without much of a reason.
> >
> > Also you can use 'ulong' instead of 'unsigned long'. It is less
> > verbose and a U-Boot standard.
> >
> > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > index 18e9c2ce99..2b9d33e964 100644
> > > --- a/MAINTAINERS
> > > +++ b/MAINTAINERS
> > > @@ -274,6 +274,7 @@ 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..059c273277 100644
> > > --- a/arch/sandbox/dts/sandbox.dtsi
> > > +++ b/arch/sandbox/dts/sandbox.dtsi
> > > @@ -445,6 +445,10 @@
> > >         thermal {
> > >                 compatible = "sandbox,thermal";
> > >         };
> > > +
> > > +       sandbox_arm_ffa {
> > > +               compatible = "sandbox,arm_ffa";
> > > +       };
> > >  };
> > >
> > >  &cros_ec {
> > > diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> > > index d72d7a567a..11dc6ed0d9 100644
> > > --- a/arch/sandbox/dts/test.dts
> > > +++ b/arch/sandbox/dts/test.dts
> > > @@ -1802,6 +1802,10 @@
> > >                 compatible = "u-boot,fwu-mdata-gpt";
> > >                 fwu-mdata-store = <&mmc0>;
> > >         };
> > > +
> > > +       sandbox_arm_ffa {
> > > +               compatible = "sandbox,arm_ffa";
> > > +       };
> >
> > I see that you have this, so the driver should bind automatically.
> >
> > Is the problem that you are trying to bind the sandbox emulator?
> > Again, you can actually add that to the DT. See how this works for
> > i2c, SPI, PCI, for example.
> >
> > >  };
> > >
> > >  #include "sandbox_pmic.dtsi"
> > > diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
> > > index ccbc18aad0..35d4676cf7 100644
> > > --- a/configs/sandbox64_defconfig
> > > +++ b/configs/sandbox64_defconfig
> > > @@ -259,3 +259,5 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
> > >  CONFIG_UNIT_TEST=y
> > >  CONFIG_UT_TIME=y
> > >  CONFIG_UT_DM=y
> > > +CONFIG_ARM_FFA_TRANSPORT=y
> > > +CONFIG_SANDBOX_FFA=y
> > > diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
> > > index a0fbdad20a..8aab8dda31 100644
> > > --- a/configs/sandbox_defconfig
> > > +++ b/configs/sandbox_defconfig
> > > @@ -336,3 +336,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/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> > > index 8fad9ef3d0..555ee9a6ae 100644
> > > --- a/doc/arch/arm64.ffa.rst
> > > +++ b/doc/arch/arm64.ffa.rst
> > > @@ -64,6 +64,10 @@ CONFIG_ARM_FFA_TRANSPORT
> > >      Enables the FF-A bus driver. Turn this on if you want to use FF-A
> > >      communication.
> > >
> > > +CONFIG_SANDBOX_FFA
> > > +    Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under
> > > +    Sandbox and provides functional tests for FF-A.
> >
> > OK that is why I am confused. Please don't call this a driver. It is
> > an emulator. When you have an emulator and a driver for the same thing
> > it gets confusing.
> >
> > > +
> > >  FF-A ABIs under the hood
> > >  ---------------------------------------
> > >
> > > diff --git a/doc/arch/sandbox/sandbox.rst b/doc/arch/sandbox/sandbox.rst
> > > index cd7f8a2cb0..c5df372e00 100644
> > > --- a/doc/arch/sandbox/sandbox.rst
> > > +++ b/doc/arch/sandbox/sandbox.rst
> > > @@ -200,6 +200,7 @@ Supported Drivers
> > >
> > >  U-Boot sandbox supports these emulations:
> > >
> > > +- Arm FF-A
> > >  - Block devices
> > >  - Chrome OS EC
> > >  - GPIO
> > > diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> > > index 2cfd7ef5fc..b5430eb6f4 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
> > > @@ -32,3 +32,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 c8d83b4bc9..d22c1ba609 100644
> > > --- a/drivers/firmware/arm-ffa/Makefile
> > > +++ b/drivers/firmware/arm-ffa/Makefile
> > > @@ -6,3 +6,4 @@
> > >  #   Abdellatif El Khlifi <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/core.c b/drivers/firmware/arm-ffa/core.c
> > > index 2210f5343c..0d2e6ff0d4 100644
> > > --- a/drivers/firmware/arm-ffa/core.c
> > > +++ b/drivers/firmware/arm-ffa/core.c
> > > @@ -1042,6 +1042,7 @@ bool ffa_try_discovery(void)
> > >         return true;
> > >  }
> > >
> > > +#if !CONFIG_IS_ENABLED(SANDBOX_FFA)
> >
> > We should not need #ifdefs here. The sandbox driver is just another
> > driver, just like there is the ARM driver. We select the correct one
> > using the devicetree and everything just works.
>
> The FF-A core driver (core.c) has Arm specific code that is not available
> when running sandbox. So we still need to use these ifdefs in core.c
> to prevent the Arm specific code from building under sandbox.
> For example these are Arm specific:
>
> arm_smccc_1_2_smc()
> struct arm_smccc_res
> ARM_SMCCC_FEATURE_DRIVER
> The SMC conduit. In sandbox mode the core driver should use the emulated conduit implemented by sandbox_arm_ffa_smccc_smc()
>
> >
> > >  /**
> > >   * __arm_ffa_fn_smc() - SMC wrapper
> > >   * @args: FF-A ABI arguments to be copied to Xn registers
> > > @@ -1069,6 +1070,7 @@ void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
> > >   * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
> > >   * So, the legacy SMC invocation is not used.
> > >   *
> > > + * In Sandbox mode sandbox_arm_ffa is used to test arm_ffa driver.
> > >   * Return:
> > >   *
> > >   * 0 on success. Otherwise, failure
> > > @@ -1088,6 +1090,30 @@ ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
> > >         .driver_name = FFA_DRV_NAME,
> > >         .is_supported = ffa_bus_is_supported,
> > >  };
> > > +#else
> > > +/* SANDBOX_FFA */
> > > +
> > > +/**
> > > + * ffa_bind() - The driver bind function
> > > + * @dev:       the arm_ffa device
> > > + * When using sandbox tries to discover the emulated FF-A bus.
> > > + * Return:
> > > + *
> > > + * 0 on success.
> > > + */
> > > +static int ffa_bind(struct udevice *dev)
> >
> > I don't think this is binding anything. How about ffa_get_dev() ?
>
> In sandbox mode, when the FF-A sandbox driver (emulates the secure world) is probed,  it calls
> device_bind_driver() to bind the FF-A core driver (a similar approach to the PSCI way).
> ffa_bind() is needed in sandbox mode so the FF-A discovery is setup properly.
>
> In an Arm platform, the PSCI driver calls the FF-A discovery callback
> ffa_bus_is_supported() which tries to discover FF-A. When discovery is successful,
> PSCI driver binds the FF-A core device by calling device_bind_driver()
>
> The core driver needs to work on both Arm and sandbox.
> The sandbox FF-A driver plays the role of a secure world emulator with which
> the FF-A core driver exchanges data.

I think there is some sort of fundamental misunderstanding of driver
model. If you put the methods in the uclass then you won't need any
#ifdefs. What am I missing?

Yes, the emulator should be called an emulator, since it is confusing
if you call it a driver.


>
> >
> > > +{
> > > +       bool ret;
> > > +
> > > +       log_info("[FFA] binding the device\n");
> > > +
> > > +       ret = ffa_try_discovery();
> > > +       if (ret)
> > > +               return 0;
> > > +       else
> > > +               return -ENODEV;
> > > +}
> > > +#endif
> > >
> > >  /**
> > >   * ffa_set_smc_conduit() - Set the SMC conduit
> > > @@ -1101,7 +1127,12 @@ ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
> > >   */
> > >  static int ffa_set_smc_conduit(void)
> > >  {
> > > -       dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc;
> > > +#if CONFIG_IS_ENABLED(SANDBOX_FFA)
> > > +               dscvry_info.invoke_ffa_fn = sandbox_arm_ffa_smccc_smc;
> > > +               log_info("[FFA] Using SMC emulation\n");
> > > +#else
> > > +               dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc;
> > > +#endif
> >
> > This needs to be reworked to go through the uclass to the correct
> > driver. Basically you need an ARM driver and a sandbox driver (which
> > attaches to the emulator).
> >
> > There should not be #idefs in this sort of code...driver model should
> > handle it. See other uclasses for examples.
>
> In sandbox we are testing the FF-A core driver. The core driver has some Arm specific code which
> explains why we need the ifdefs. In Arm the SMC conduit is implemented by __arm_ffa_fn_smc()
> which ends up calling Arm instructions.
> When building the core driver with sandbox, the SMC conduit is set to the emulated version of the SMC calls
> implemented by sandbox_arm_ffa_smccc_smc()
>
> I'm happy to rename the FF-A sandbox driver to the FF-A sandbox emulator if that clears the doubts.
> However, the emulator is still a driver and bound to a sandbox device (the parent of the core).
>
> Cheers,
> Abdellatif
>
> >
> > >
> > >         log_info("[FFA] Conduit is SMC\n");
> > >
> > > @@ -1246,4 +1277,7 @@ U_BOOT_DRIVER(arm_ffa) = {
> > >         .remove = ffa_remove,
> > >         .unbind = ffa_unbind,
> > >         .ops            = &ffa_ops,
> > > +#if CONFIG_IS_ENABLED(SANDBOX_FFA)
> > > +       .bind           = ffa_bind,
> >
> > Can drop this
> >
> > > +#endif
> > >  };
> > > diff --git a/drivers/firmware/arm-ffa/sandbox.c b/drivers/firmware/arm-ffa/sandbox.c
> >
> > sandbox_emul.c pehaps?
> >
> > I am pretty sure this is an emulator
> >
> > > new file mode 100644
> > > index 0000000000..84c2fc929f
> > > --- /dev/null
> > > +++ b/drivers/firmware/arm-ffa/sandbox.c
> > > @@ -0,0 +1,610 @@
> > > +// 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 <dm/device-internal.h>
> > > +#include <dm/lists.h>
> > > +#include <dm/root.h>
> > > +#include <linux/errno.h>
> > > +#include <linux/sizes.h>
> > > +#include "sandbox_arm_ffa_priv.h"
> > > +
> > > +DECLARE_GLOBAL_DATA_PTR;
> > > +
> > > +/* The partitions (SPs) table */
> > > +static struct ffa_partition_desc sandbox_partitions[SANDBOX_PARTITIONS_CNT] = {
> > > +       {
> > > +               .info = { .id = SANDBOX_SP1_ID, .exec_ctxt = 0x5687, .properties = 0x89325621 },
> > > +               .sp_uuid = {
> > > +                       .a1 = SANDBOX_SERVICE1_UUID_A1,
> > > +                       .a2 = SANDBOX_SERVICE1_UUID_A2,
> > > +                       .a3 = SANDBOX_SERVICE1_UUID_A3,
> > > +                       .a4 = SANDBOX_SERVICE1_UUID_A4,
> > > +               }
> > > +       },
> > > +       {
> > > +               .info = { .id = SANDBOX_SP2_ID, .exec_ctxt = 0x9587, .properties = 0x45325621 },
> > > +               .sp_uuid = {
> > > +                       .a1 = SANDBOX_SERVICE2_UUID_A1,
> > > +                       .a2 = SANDBOX_SERVICE2_UUID_A2,
> > > +                       .a3 = SANDBOX_SERVICE2_UUID_A3,
> > > +                       .a4 = SANDBOX_SERVICE2_UUID_A4,
> > > +               }
> > > +       },
> > > +       {
> > > +               .info = { .id = SANDBOX_SP3_ID, .exec_ctxt = 0x7687, .properties = 0x23325621 },
> > > +               .sp_uuid = {
> > > +                       .a1 = SANDBOX_SERVICE1_UUID_A1,
> > > +                       .a2 = SANDBOX_SERVICE1_UUID_A2,
> > > +                       .a3 = SANDBOX_SERVICE1_UUID_A3,
> > > +                       .a4 = SANDBOX_SERVICE1_UUID_A4,
> > > +               }
> > > +       },
> > > +       {
> > > +               .info = { .id = SANDBOX_SP4_ID, .exec_ctxt = 0x1487, .properties = 0x70325621 },
> > > +               .sp_uuid = {
> > > +                       .a1 = SANDBOX_SERVICE2_UUID_A1,
> > > +                       .a2 = SANDBOX_SERVICE2_UUID_A2,
> > > +                       .a3 = SANDBOX_SERVICE2_UUID_A3,
> > > +                       .a4 = SANDBOX_SERVICE2_UUID_A4,
> > > +               }
> > > +       }
> > > +
> > > +};
> > > +
> > > +/* Driver functions */
> > > +
> > > +/**
> > > + * sandbox_ffa_version() - Emulated FFA_VERSION handler function
> > > + * @dev:       the sandbox FF-A device
> > > + * @{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)
> >
> > Instead of the macro can you write this out in full? It defeats ctags, etc.
> >
> > > +{
> > > +       struct sandbox_ffa_priv *priv = dev_get_priv(dev);
> > > +
> > > +       priv->fwk_version = FFA_VERSION_1_0;
> > > +       res->a0 = priv->fwk_version;
> >
> > Where is res defined?
> >
> > > +
> > > +       /* 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
> > > + * @dev:       the sandbox FF-A device
> > > + * @{a0-a7} , res: The SMC call arguments and return structure.
> > > + *
> > > + * This is the function that emulates FFA_ID_GET FF-A function.
> >
> > s/This is the function that e/E/g
> >
> > > + *
> > > + * Return:
> > > + *
> > > + * 0 on success. Otherwise, failure
> > > + */
> > > +SANDBOX_SMC_FFA_ABI(ffa_id_get)
> > > +{
> > > +       struct sandbox_ffa_priv *priv = dev_get_priv(dev);
> > > +
> > > +       res->a0 = FFA_SMC_32(FFA_SUCCESS);
> > > +       res->a1 = 0;
> > > +
> > > +       priv->id = NS_PHYS_ENDPOINT_ID;
> > > +       res->a2 = priv->id;
> > > +
> > > +       /* x3-x7 MBZ */
> > > +       memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long));
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +/**
> > > + * sandbox_ffa_features() - Emulated FFA_FEATURES handler function
> > > + * @dev:       the sandbox FF-A device
> > > + * @{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));
> > > +               log_err("[FFA] [Sandbox] FF-A interface 0x%lx not implemented\n", pargs->a1);
> >
> > return -ENOSYS
> >
> > > +       }
> > > +
> > > +       res->a1 = 0;
> > > +
> > > +       return 0;
> > > +}
> > > +
> >
> > [..]
> >
> > > +SANDBOX_SMC_FFA_ABI(ffa_msg_send_direct_req)
> > > +{
> > > +       u16 part_id;
> > > +       struct sandbox_ffa_priv *priv = dev_get_priv(dev);
> > > +
> > > +       part_id = GET_DST_SP_ID(pargs->a1);
> > > +
> > > +       if ((GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id) ||
> >
> > drop extra brackets
> >
> > > +           !sandbox_ffa_sp_valid(dev, 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(priv->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;
> >
> > Would -1UL work?
> >
> > > +
> > > +       return 0;
> > > +}
> > > +
> >
> > [..]
> >
> > > +static int sandbox_ffa_probe(struct udevice *dev)
> > > +{
> > > +       struct udevice *child_dev = NULL;
> > > +       int ret;
> > > +
> > > +       ret = device_bind_driver(dev, FFA_DRV_NAME, FFA_DRV_NAME, &child_dev);
> >
> > Is this binding the emulator? Add it to the DT instead.
> >
> > If you put
> >
> > .post_bind = dm_scan_fdt_dev()
> >
> > in your uclass (like spi-uclass.c does) then it will binding
> > child-node devices automatically. Then you can make your emulator a
> > child node.
> >
> > > +       if (ret) {
> > > +               pr_err("%s was not bound: %d, aborting\n", FFA_DRV_NAME, ret);
> > > +               return -ENODEV;
> > > +       }
> > > +
> > > +       dev_set_parent_plat(child_dev, dev_get_plat(dev));
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static const struct udevice_id sandbox_ffa_id[] = {
> > > +       { "sandbox,arm_ffa", 0 },
> > > +       { },
> > > +};
> > > +
> > > +/* Declaring the sandbox_arm_ffa driver under UCLASS_FFA */
> > > +U_BOOT_DRIVER(sandbox_arm_ffa) = {
> > > +       .name           = FFA_SANDBOX_DRV_NAME,
> > > +       .of_match = sandbox_ffa_id,
> > > +       .id             = UCLASS_FFA,
> > > +       .probe          = sandbox_ffa_probe,
> > > +       .priv_auto      = sizeof(struct sandbox_ffa_priv),
> > > +};
> > > diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> > > new file mode 100644
> > > index 0000000000..c35d80de16
> > > --- /dev/null
> > > +++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> > > @@ -0,0 +1,129 @@
> > > +/* 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 <sandbox_arm_ffa.h>
> > > +#include "arm_ffa_priv.h"
> > > +
> > > +/* This header is exclusively used by the Sandbox FF-A driver and sandbox tests */
> > > +
> > > +/* 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
> >
> > It's a convention to put negative values in brackets just in case of
> > operator-precedence issues. Or you could use an enum.
> >
> > > +
> > > +/* 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 secure partitions emulated by the FF-A sandbox driver */
> > > +#define SANDBOX_PARTITIONS_CNT (4)
> > > +
> > > +/* Binary data of services UUIDs emulated by the FF-A sandbox driver */
> > > +
> > > +/* 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_priv - 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_priv {
> > > +       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(struct udevice *dev, \
> > > +                                                             ffa_value_t *pargs, ffa_value_t *res)
> >
> > drop that
> >
> > [..]
Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v10 00/10] introduce Arm FF-A support
  2023-03-10 20:50                                                                                     ` [PATCH v9 00/10] introduce Arm FF-A support Simon Glass
@ 2023-03-28 16:11                                                                                       ` Abdellatif El Khlifi
  2023-03-28 16:11                                                                                         ` [PATCH v10 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                                                                           ` (10 more replies)
  0 siblings, 11 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-28 16:11 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong, Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].

FF-A describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World. These interfaces enable a pair of
software sandboxes to communicate with each other. A sandbox aka partition could
be a VM in the Normal or Secure world, an application in S-EL0, or a
Trusted OS in S-EL1.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

   => dm tree

    Class     Index  Probed  Driver                Name
   -----------------------------------------------------------
   ...
    firmware      0  [ + ]   psci                      |-- psci
    ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
   ...

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_get_device_by_name).

This implementation of the specification provides support for Aarch64.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

    - Discover the presence of secure partitions (SPs) of interest
    - Access an SP's service through communication protocols
      e.g. EFI MM communication protocol

The FF-A support provides the following features:

    - Being generic by design and can be used by any Arm 64-bit platform
    - A Uclass driver providing generic FF-A methods and driver operations
    - An Arm FF-A device driver
    - FF-A support can be compiled and used without EFI
    - Support for SMCCCv1.2 x0-x17 registers
    - Support for SMC32 calling convention
    - Support for 32-bit and 64-bit FF-A direct messaging
    - A new command called armffa is provided as an example of how to access the
      FF-A bus
    - Support for FF-A MM communication (compatible with EFI boot time)
    - Enabling FF-A and MM communication in Corstone1000 platform as a use case
    - A sandbox emulator for Arm FF-A
    - An FF-A sandbox device driver
    - Sandbox FF-A test cases

For more details about the FF-A core driver please refer to [B] and refer to [C] for
how to use the armffa command.

Please find at [D] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of the major changes:
===========================

v10:

* provide the FF-A driver operations through the Uclass (arm-ffa-uclass.c)
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c renamed from core.c)
* split the FF-A sandbox support into an emulator (ffa-emul-uclass.c) and a driver (sandbox_ffa.c)
* use the FF-A driver Uclass operations by clients (armffa command, tests, MM comms)
* use uclass_first_device to search and probe the FF-A device (whether it is on Arm or on sandbox)
* address nits

v9: [9]

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
* align FF-A sandbox driver with FF-A discovery through DM
* use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
* add documentation for the armffa command: doc/usage/cmd/armffa.rst
* introduce testcase for uuid_str_to_le_bin

v8: [8]

* pass the FF-A bus device to the bus operations
* isolate the compilation choices between FF-A and OP-TEE
* drop OP-TEE configs from Corstone-1000 defconfig
* make ffa_get_partitions_info() second argument to be an SP count in both
  modes

v7: [7]

* add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v6: [6]

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

List of previous patches:

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
[7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
[8]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
[9]: https://lore.kernel.org/all/20230310141016.137986-1-abdellatif.elkhlifi@arm.com/

More details:

[A]: https://developer.arm.com/documentation/den0077/latest/
[B]: doc/arch/arm64.ffa.rst
[C]: doc/usage/cmd/armffa.rst
[D]: example of boot logs when enabling FF-A

```
U-Boot 2023.01 (Mar 27 2023 - 13:48:33 +0000) corstone1000 aarch64 

DRAM:  2 GiB
[FFA] trying FF-A framework discovery
[FFA] Using Arm SMC for FF-A conduit
[FFA] FF-A driver 1.0
FF-A framework 1.0
[FFA] Versions are compatible
...
Hit any key to stop autoboot:  0 
...
[FFA] endpoint ID is 0
[FFA] Using 1 4KB page(s) for RX/TX buffers size
[FFA] RX buffer at virtual address 00000000fdf4f000
[FFA] TX buffer at virtual address 00000000fdf51000
[FFA] RX/TX buffers mapped
[FFA] Reading partitions data from the RX buffer
[FFA] Partition ID 8001 : info cached
[FFA] Partition ID 8002 : info cached
[FFA] Partition ID 8003 : info cached
[FFA] 3 partition(s) found and cached
[FFA] Preparing for checking partitions count
[FFA] Searching partitions using the provided UUID
[FFA] No partition found. Querying framework ...
[FFA] Reading partitions data from the RX buffer
[FFA] Number of partition(s) matching the UUID: 1
EFI: Pre-allocating 1 partition(s) info structures
[FFA] Preparing for filling partitions info
[FFA] Searching partitions using the provided UUID
[FFA] Partition ID 8003 matches the provided UUID
EFI: MM partition ID 0x8003
EFI: Corstone1000: Capsule shared buffer at 0x80000000 , size 8192 pages
Booting /MemoryMapped(0x0,0x88200000,0xf00000)
EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from configuration table
EFI stub: Exiting boot services...
[FFA] removing the device
[FFA] unmapping RX/TX buffers
[FFA] Freeing RX/TX buffers
Booting Linux on physical CPU 0x0000000000 [0x411fd040]
Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
Machine model: ARM Corstone1000 FPGA MPS3 board
```

Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (10):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce uuid_str_to_le_bin function
  lib: uuid: introduce testcase for uuid_str_to_le_bin
  arm_ffa: introduce Arm FF-A support
  arm_ffa: introduce armffa command
  arm_ffa: introduce sandbox FF-A support
  arm_ffa: introduce sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   18 +
 arch/arm/cpu/armv8/smccc-call.S               |   57 +-
 arch/arm/lib/asm-offsets.c                    |   16 +
 arch/sandbox/dts/sandbox.dtsi                 |    8 +
 arch/sandbox/dts/test.dts                     |    8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |   68 +
 .../include/asm/sandbox_arm_ffa_priv.h        |  133 ++
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    2 +
 cmd/armffa.c                                  |  238 ++++
 configs/corstone1000_defconfig                |    2 +
 configs/sandbox64_defconfig                   |    1 +
 configs/sandbox_defconfig                     |    1 +
 doc/arch/arm64.ffa.rst                        |  292 ++++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox/sandbox.rst                  |    1 +
 doc/usage/cmd/armffa.rst                      |  107 ++
 doc/usage/index.rst                           |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   42 +
 drivers/firmware/arm-ffa/Makefile             |   16 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1258 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  148 ++
 drivers/firmware/arm-ffa/ffa-emul-uclass.c    |  732 ++++++++++
 drivers/firmware/arm-ffa/sandbox_ffa.c        |  108 ++
 include/arm_ffa.h                             |  269 ++++
 include/arm_ffa_priv.h                        |  254 ++++
 include/configs/corstone1000.h                |   15 +-
 include/dm/uclass-id.h                        |    7 +
 include/linux/arm-smccc.h                     |   45 +
 include/mm_communication.h                    |    6 +
 include/uuid.h                                |   15 +
 lib/efi_loader/Kconfig                        |   14 +-
 lib/efi_loader/efi_variable_tee.c             |  300 +++-
 lib/uuid.c                                    |   48 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   39 +
 test/dm/Makefile                              |    2 +
 test/dm/ffa.c                                 |  357 +++++
 test/lib/Makefile                             |    1 +
 test/lib/uuid.c                               |   44 +
 42 files changed, 4679 insertions(+), 9 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 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 doc/usage/cmd/armffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/lib/uuid.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v10 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-03-28 16:11                                                                                       ` [PATCH v10 " Abdellatif El Khlifi
@ 2023-03-28 16:11                                                                                         ` Abdellatif El Khlifi
  2023-03-29 20:02                                                                                           ` Simon Glass
  2023-03-28 16:11                                                                                         ` [PATCH v10 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
                                                                                                           ` (9 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-28 16:11 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>

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

v9:

* update the copyright string

v7:

* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

 arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
 arch/arm/lib/asm-offsets.c      | 16 +++++++++
 include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..93f66d3366 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,7 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
- */
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+*/
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
 #include <generated/asm-offsets.h>
@@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 6de0ce9152..181a8ac4c2 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,11 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * 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>
@@ -90,6 +95,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#ifdef CONFIG_ARM64
+	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..f44e9e8f93 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +74,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v10 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2023-03-28 16:11                                                                                       ` [PATCH v10 " Abdellatif El Khlifi
  2023-03-28 16:11                                                                                         ` [PATCH v10 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-03-28 16:11                                                                                         ` Abdellatif El Khlifi
  2023-03-28 16:11                                                                                         ` [PATCH v10 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
                                                                                                           ` (8 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-28 16:11 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

convert UUID string to little endian binary data

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
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>

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

v9:

* add a full function prototype description in uuid.h

v8:

* use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

 include/uuid.h | 15 +++++++++++++++
 lib/uuid.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..89b93e642b 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,10 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +48,15 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ * Return:
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 96e1af3c8b..45f325d964 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * 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>
@@ -354,6 +358,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16;
+	u32 tmp32;
+	u64 tmp64;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+	memcpy(uuid_bin, &tmp32, 4);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16));
+	memcpy(uuid_bin + 10, &tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v10 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-03-28 16:11                                                                                       ` [PATCH v10 " Abdellatif El Khlifi
  2023-03-28 16:11                                                                                         ` [PATCH v10 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2023-03-28 16:11                                                                                         ` [PATCH v10 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2023-03-28 16:11                                                                                         ` Abdellatif El Khlifi
  2023-03-29 20:02                                                                                           ` Simon Glass
  2023-03-28 16:11                                                                                         ` [PATCH v10 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                           ` (7 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-28 16:11 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

provide a test case

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Simon Glass <sjg@chromium.org>
---
 MAINTAINERS       |  5 +++++
 test/lib/Makefile |  1 +
 test/lib/uuid.c   | 44 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 50 insertions(+)
 create mode 100644 test/lib/uuid.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 91d40ea4b6..dc3af17e61 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1601,3 +1601,8 @@ S:	Maintained
 F:	arch/arm/dts/ls1021a-twr-u-boot.dtsi
 F:	drivers/crypto/fsl/
 F:	include/fsl_sec.h
+
+UUID testing
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	test/lib/uuid.c
diff --git a/test/lib/Makefile b/test/lib/Makefile
index e0bd9e04e8..e75a263e6a 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_AES) += test_aes.o
 obj-$(CONFIG_GETOPT) += getopt.o
 obj-$(CONFIG_CRC8) += test_crc8.o
 obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o
+obj-$(CONFIG_LIB_UUID) += uuid.o
 else
 obj-$(CONFIG_SANDBOX) += kconfig_spl.o
 endif
diff --git a/test/lib/uuid.c b/test/lib/uuid.c
new file mode 100644
index 0000000000..6f24939de4
--- /dev/null
+++ b/test/lib/uuid.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <uuid.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* test UUID */
+#define TEST_SVC_UUID	"ed32d533-4209-99e6-2d72-cdd998a79cc0"
+
+#define UUID_SIZE 16
+
+/* The UUID binary data (little-endian format) */
+static const u8 ref_uuid_bin[UUID_SIZE] = {
+	0x33, 0xd5, 0x32, 0xed,
+	0x09, 0x42, 0xe6, 0x99,
+	0x72, 0x2d, 0xc0, 0x9c,
+	0xa7, 0x98, 0xd9, 0xcd
+};
+
+static int lib_test_uuid_to_le(struct unit_test_state *uts)
+{
+	const char *uuid_str = TEST_SVC_UUID;
+	u8 ret_uuid_bin[UUID_SIZE] = {0};
+	int cnt;
+
+	ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin));
+
+	for (cnt = 0; cnt < UUID_SIZE; cnt++)
+		ut_asserteq(ref_uuid_bin[cnt], ret_uuid_bin[cnt]);
+
+	return 0;
+}
+
+LIB_TEST(lib_test_uuid_to_le, 0);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v10 04/10] arm_ffa: introduce Arm FF-A support
  2023-03-28 16:11                                                                                       ` [PATCH v10 " Abdellatif El Khlifi
                                                                                                           ` (2 preceding siblings ...)
  2023-03-28 16:11                                                                                         ` [PATCH v10 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-03-28 16:11                                                                                         ` Abdellatif El Khlifi
  2023-04-02  2:41                                                                                           ` Simon Glass
  2023-03-28 16:11                                                                                         ` [PATCH v10 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                                                                           ` (6 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-28 16:11 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong, Heinrich Schuchardt

Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- ffa_partition_info_get
- ffa_sync_send_receive
- ffa_rxtx_unmap

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 please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

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

v10:

* provide the driver operations through the Uclass
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c)
* rename core.c to arm-ffa.c
* address nits

v9:

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding

v8:

* make ffa_get_partitions_info() second argument to be an SP count in both
  modes
* update ffa_bus_prvdata_get() to return a pointer rather than a pointer
  address
* remove packing from ffa_partition_info and ffa_send_direct_data structures
* pass the FF-A bus device to the bus operations

v7:

* add support for 32-bit direct messaging
* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* improve the declaration of error handling mapping
* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the U-Boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the U-Boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

 MAINTAINERS                                   |    8 +
 doc/arch/arm64.ffa.rst                        |  279 ++++
 doc/arch/index.rst                            |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   36 +
 drivers/firmware/arm-ffa/Makefile             |    8 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1258 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  148 ++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |   14 +
 include/arm_ffa.h                             |  269 ++++
 include/arm_ffa_priv.h                        |  254 ++++
 include/dm/uclass-id.h                        |    6 +
 13 files changed, 2283 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h

diff --git a/MAINTAINERS b/MAINTAINERS
index dc3af17e61..62c30184bb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,6 +266,14 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+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>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..ddf6435402
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,279 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Support
+================
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software sandboxes to
+communicate with each other. A sandbox aka partition could
+be a VM in the Normal or Secure world, an application in S-EL0, or a
+Trusted OS in S-EL1.
+
+The U-Boot FF-A support (the bus) implements the interfaces to communicate
+with partitions in the Secure world aka Secure partitions (SPs).
+
+The FF-A support specifically focuses on communicating with SPs that
+isolate portions of EFI runtime services that must run in a protected
+environment which is inaccessible by the Host OS or Hypervisor.
+Examples of such services are set/get variables.
+
+The FF-A support uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+At this stage of development only EFI boot time is supported.
+Runtime support will be added in future developments.
+
+The U-Boot FF-A support provides the following parts:
+
+- A Uclass driver providing generic FF-A methods.
+- An Arm FF-A driver providing Arm specific methods and reusing the Uclass methods.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the U-Boot FF-A support relies on FF-A
+specification v1.0 and uses SMC32 calling convention which means using
+the first 32-bit data of the Xn registers.
+
+At this stage we only need the FF-A v1.0 features.
+
+The FF-A support has been tested with OP-TEE which supports SMC32 calling
+convention.
+
+For more details please refer to the FF-A v1.0 spec:
+https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A support uses 64-bit registers as per SMCCCv1.2 specification.
+
+For more details please refer to the SMC Calling Convention v1.2 spec:
+https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+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.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers.
+Then, an SMC instruction is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-Boot Arm FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs.
+
+FF-A bus discovery on Arm 64-bit platforms
+---------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
+an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
+This discovery mechanism is performed by the PSCI driver.
+
+The PSCI driver comes with a PSCI device tree node which is the root node for all
+architecture features including FF-A bus.
+
+::
+
+   => dm tree
+
+    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.
+
+In case of FF-A, the callback is ffa_bus_is_supported() which tries to discover the
+FF-A framework by querying the FF-A framework version from secure world using
+FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
+mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver
+with the device using device_bind_driver().
+
+At this stage the FF-A bus is registered with the DM and can be interacted with using
+the DM APIs.
+
+Clients are able to probe then use the FF-A bus by calling uclass_first_device().
+Please refer to the armffa command implementation as an example of how to probe
+and interact with the FF-A bus.
+
+When calling uclass_first_device(), the FF-A driver is probed and ends up calling
+ffa_do_probe() provided by the Uclass which does the following:
+
+    - allocating private data (priv) with devres
+    - updating priv with discovery information
+    - querying from secure world the u-boot endpoint ID
+    - querying from secure world the supported features of FFA_RXTX_MAP
+    - mapping the RX/TX buffers
+    - querying from secure world all the partitions information
+
+When one of the above actions fails, probing fails and the driver stays not active
+and can be probed again if needed.
+
+FF-A device destruction
+-------------------------
+
+When the FF-A device is removed by the DM, RX/TX buffers are automatically
+unmapped and freed. Same happens when the device is unbound before being
+removed first.
+
+For example, at EFI efi_exit_boot_services() active devices are automatically removed
+by dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL).
+
+By consequence, the FF-A RX/TX are unmapped automatically.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must query the SPs they are looking for
+during EFI boot time mode using the service UUID.
+
+The RX/TX buffers are only available at EFI boot time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped before EFI runtime mode starts.
+The driver provides a bus operation for that called rxtx_unmap() and this is done
+automatically at efi_exit_boot_services().
+
+If  RX/TX buffers created by U-Boot are not unmapped and by consequence becoming
+available at EFI runtime, secure world will get confused about RX/TX buffers
+ownership (U-Boot vs kernel).
+
+When invoking FF-A direct messaging, clients should specify which ABI protocol
+they want to use (32-bit vs 64-bit). Selecting the protocol means using
+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
+The calling convention between U-Boot and the secure world stays the same: SMC32.
+
+The bus driver layer
+------------------------------
+
+FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c
+
+The following features are provided:
+
+- Support for the 32-bit version of the following ABIs:
+
+    - FFA_VERSION
+    - FFA_ID_GET
+    - FFA_FEATURES
+    - FFA_PARTITION_INFO_GET
+    - FFA_RXTX_UNMAP
+    - FFA_RX_RELEASE
+    - FFA_RUN
+    - FFA_ERROR
+    - FFA_SUCCESS
+    - FFA_INTERRUPT
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Support for the 64-bit version of the following ABIs:
+
+    - FFA_RXTX_MAP
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, FF-A support takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- FF-A support provides driver operations to be used by upper layers:
+
+    - ffa_partition_info_get
+    - ffa_sync_send_receive
+    - ffa_rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+Example of boot logs with FF-A enabled
+--------------------------------------
+
+For example, when using FF-A with Corstone-1000 the logs are as follows:
+
+::
+
+   U-Boot 2023.01 (Mar 07 2023 - 11:05:21 +0000) corstone1000 aarch64
+
+   DRAM:  2 GiB
+   [FFA] trying FF-A framework discovery
+   [FFA] Conduit is SMC
+   [FFA] FF-A driver 1.0
+   FF-A framework 1.0
+   [FFA] Versions are compatible
+   Core:  18 devices, 12 uclasses, devicetree: separate
+   MMC:
+   Loading Environment from nowhere... OK
+   ...
+   Hit any key to stop autoboot:  0
+   Loading kernel from 0x083EE000 to memory ...
+   ...
+   [FFA] endpoint ID is 0
+   [FFA] Using 1 4KB page(s) for RX/TX buffers size
+   [FFA] RX buffer at virtual address 00000000fdf4e000
+   [FFA] TX buffer at virtual address 00000000fdf50000
+   [FFA] RX/TX buffers mapped
+   [FFA] Reading partitions data from the RX buffer
+   [FFA] Partition ID 8001 : info cached
+   [FFA] Partition ID 8002 : info cached
+   [FFA] Partition ID 8003 : info cached
+   [FFA] 3 partition(s) found and cached
+   [FFA] Preparing for checking partitions count
+   [FFA] Searching partitions using the provided UUID
+   [FFA] No partition found. Querying framework ...
+   [FFA] Reading partitions data from the RX buffer
+   [FFA] Number of partition(s) matching the UUID: 1
+   EFI: Pre-allocating 1 partition(s) info structures
+   [FFA] Preparing for filling partitions info
+   [FFA] Searching partitions using the provided UUID
+   [FFA] Partition ID 8003 matches the provided UUID
+   EFI: MM partition ID 0x8003
+   EFI: Corstone1000: Capsule shared buffer at 0x80000000 , size 8192 pages
+   Booting /MemoryMapped(0x0,0x88200000,0xf00000)
+   EFI stub: Booting Linux Kernel...
+   EFI stub: Using DTB from configuration table
+   EFI stub: Exiting boot services...
+   [FFA] removing the device
+   [FFA] unmapping RX/TX buffers
+   [FFA] Freeing RX/TX buffers
+   Booting Linux on physical CPU 0x0000000000 [0x411fd040]
+   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
+   Machine model: ARM Corstone1000 FPGA MPS3 board
+   efi: EFI v2.100 by Das U-Boot
+   ...
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index b8da4b8c8e..2f916f4026 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Makefile b/drivers/Makefile
index 58be410135..885fdef4dc 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -112,6 +112,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index eae1c8ddc9..8789b1ea14 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
 	  the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
 	  services if any and reported as supported by the SMCCC firmware.
 
+source "drivers/firmware/arm-ffa/Kconfig"
 source "drivers/firmware/scmi/Kconfig"
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..9200c8028b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select ARM_SMCCC_FEATURES
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
+	  FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
+	  by the PSCI driver.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  The FF-A support on U-Boot  takes care of all the interactions between Normal
+	  world and Secure World.
+
+	  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
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..11b1766285
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,8 @@
+# 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>
+
+obj-y += arm-ffa-uclass.o arm-ffa.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..c387c26323
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,1258 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* FF-A discovery information */
+struct ffa_discovery_info dscvry_info;
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	[NOT_SUPPORTED] = -EOPNOTSUPP,
+	[INVALID_PARAMETERS] = -EINVAL,
+	[NO_MEMORY] = -ENOMEM,
+	[BUSY] = -EBUSY,
+	[INTERRUPTED] = -EINTR,
+	[DENIED] = -EACCES,
+	[RETRY] = -EAGAIN,
+	[ABORTED] = -ECANCELED,
+};
+
+static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			[NO_MEMORY] =
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			[BUSY] =
+			"BUSY: RX buffer of the caller is not free",
+			[DENIED] =
+			"DENIED: Callee is not in a state to handle this request",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			[DENIED] =
+			"DENIED: Caller did not have ownership of the RX buffer",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			[NO_MEMORY] =
+			"NO_MEMORY: Not enough memory",
+			[DENIED] =
+			"DENIED: Buffer pair already registered",
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno() - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This function maps the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+static int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* Map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * This function maps the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+static int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* Map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	log_err("[FFA] %s\n", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/* FF-A ABIs implementation (U-Boot side) */
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ *
+ * This function implements FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_version_hdlr(void)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	if (!dscvry_info.invoke_ffa_fn)
+		return -EINVAL;
+
+	dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	log_info("[FFA] FF-A driver %d.%d\nFF-A framework %d.%d\n",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) {
+		log_info("[FFA] Versions are compatible\n");
+
+		dscvry_info.fwk_version = res.a0;
+
+		return 0;
+	}
+
+	log_err("[FFA] versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id() - FFA_ID_GET handler function
+ * @dev: The FF-A bus device
+ *
+ * This function implements FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		log_info("[FFA] endpoint ID is %u\n", priv->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt() - sets the minimum number of pages in each of the RX/TX buffers
+ * @dev: The FF-A bus device
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * This function sets the minimum number of pages
+ *  in each of the RX/TX buffers in the private data structure
+ *
+ * Return:
+ *
+ * buf_4k_pages points to the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field)
+{
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	switch (prop_field) {
+	case RXTX_4K:
+		priv->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		priv->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		priv->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		log_err("[FFA] RX/TX buffer size not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features_hdlr() - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ * @dev: The FF-A bus device
+ *
+ * This function implements FFA_FEATURES FF-A function
+ * to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers() - frees the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * This  function  frees the RX/TX buffers
+ */
+static void ffa_free_rxtx_buffers(struct udevice *dev)
+{
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	log_info("[FFA] Freeing RX/TX buffers\n");
+
+	if (priv->pair.rxbuf) {
+		free(priv->pair.rxbuf);
+		priv->pair.rxbuf = NULL;
+	}
+
+	if (priv->pair.txbuf) {
+		free(priv->pair.txbuf);
+		priv->pair.txbuf = NULL;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers() - allocates the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * This function is used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(struct udevice *dev)
+{
+	u64 bytes;
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	log_info("[FFA] Using %lu 4KB page(s) for RX/TX buffers size\n",
+		 priv->pair.rxtx_min_pages);
+
+	bytes = priv->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 * Assumption: Memory allocated with memalign is always physically contiguous
+	 */
+
+	priv->pair.rxbuf = memalign(bytes, bytes);
+	if (!priv->pair.rxbuf) {
+		log_err("[FFA] failure to allocate RX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_info("[FFA] RX buffer at virtual address %p\n", priv->pair.rxbuf);
+
+	priv->pair.txbuf = memalign(bytes, bytes);
+	if (!priv->pair.txbuf) {
+		free(priv->pair.rxbuf);
+		priv->pair.rxbuf = NULL;
+		log_err("[FFA] failure to allocate the TX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_info("[FFA] TX buffer at virtual address %p\n", priv->pair.txbuf);
+
+	/* Make sure the buffers are cleared before use */
+	memset(priv->pair.rxbuf, 0, bytes);
+	memset(priv->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers_hdlr() - FFA_RXTX_MAP handler function
+ * @dev: The FF-A bus device
+ *
+ * This function implements FFA_RXTX_MAP FF-A function
+ * to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	ret = ffa_alloc_rxtx_buffers(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 * no need to convert from virtual to physical
+	 */
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = map_to_sysmem(priv->pair.txbuf),
+			.a2 = map_to_sysmem(priv->pair.rxbuf),
+			.a3 = priv->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		log_info("[FFA] RX/TX buffers mapped\n");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers(dev);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The FF-A bus device
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *priv = NULL;
+
+	if (!dev)
+		return -ENODEV;
+
+	log_info("[FFA] unmapping RX/TX buffers\n");
+
+	priv = dev_get_priv(dev);
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(priv->id),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers(dev);
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer_hdlr() - FFA_RX_RELEASE handler function
+ * @dev: The FF-A bus device
+ *
+ * This function invokes FFA_RX_RELEASE FF-A function
+ * to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical() - checks whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * This function is used by ffa_read_partitions_info to search
+ * for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+static bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+				   const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info() - reads queried partition data
+ * @dev: The FF-A bus device
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * This function reads the partitions information
+ * returned by the FFA_PARTITION_INFO_GET and saves it in the private
+ * data structure.
+ *
+ * Return:
+ *
+ * The private data structure is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(struct udevice *dev, u32 count,
+				    struct ffa_partition_uuid *part_uuid)
+{
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	if (!count) {
+		log_err("[FFA] no partition detected\n");
+		return -ENODATA;
+	}
+
+	log_info("[FFA] Reading partitions data from the RX buffer\n");
+
+	if (!part_uuid) {
+		/* Querying information of all partitions */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = priv->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			log_err("[FFA] partitions data size exceeds the RX buffer size:\n");
+			log_err("[FFA]     sizes in bytes: data %llu , RX buffer %llu\n",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO);
+		if (!priv->partitions.descs) {
+			log_err("[FFA] cannot  allocate partitions data buffer\n");
+			return -ENOMEM;
+		}
+
+		parts_info = priv->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			priv->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			log_info("[FFA] Partition ID %x : info cached\n",
+				 priv->partitions.descs[desc_idx].info.id);
+		}
+
+		priv->partitions.count = count;
+
+		log_info("[FFA] %d partition(s) found and cached\n", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = priv->pair.rxbuf;
+
+		/*
+		 * Search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/* Search the current ID in the cached partitions */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < priv->partitions.count;
+			     cached_desc_idx++) {
+				/* Save the UUID */
+				if (priv->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					priv->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info() - invokes FFA_PARTITION_INFO_GET and saves partitions data
+ * @dev: The FF-A bus device
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * This function executes the FFA_PARTITION_INFO_GET
+ * to query the partitions data. Then, it calls ffa_read_partitions_info
+ * to save the data in the private data structure.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid);
+			if (ret) {
+				log_err("[FFA] failed reading SP(s) data , err (%d)\n", ret);
+				ffa_release_rx_buffer_hdlr(dev);
+				return -EINVAL;
+			}
+		}
+
+		/* Return the SP count (when querying using a UUID) */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer_hdlr(dev);
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of partitions
+ *			 The variable will be set by the driver
+ *	@buffer: NULL
+ *
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@dev: The FF-A bus device
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of empty partition descriptors
+ *			 The variable will be read by the driver
+ *	@buffer: pointer to SPs information buffer
+ *		(allocated by the client and contains empty @sp_count descriptors).
+ *		The buffer will be filled by the driver
+ *
+ * This function queries the secure partition data from
+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * When invoked through a client request, ffa_get_partitions_info_hdlr() should be
+ * called twice. First call is to get from the driver the number of secure
+ * partitions (SPs) associated to a particular UUID.
+ * Then, the caller (client) allocates the buffer to host the SPs data and
+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
+ * buffer.
+ *
+ * To achieve the mechanism described above, ffa_get_partitions_info_hdlr() uses the
+ * following functions:
+ *		ffa_read_partitions_info
+ *		ffa_query_partitions_info
+ *
+ * Return:
+ *
+ * @sp_count: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer size, the buffer will be
+ * filled by the driver.
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_info *buffer)
+{
+	/*
+	 * fill_data:
+	 * 0: return the SP count
+	 * 1: fill SP data and return it to the caller
+	 */
+	bool fill_data = 0;
+	u32 desc_idx, client_desc_idx;
+	struct ffa_partition_uuid part_uuid = {0};
+	u32 sp_found = 0;
+	struct ffa_priv *priv = NULL;
+
+	if (!dev)
+		return -ENODEV;
+
+	priv = dev_get_priv(dev);
+
+	if (!priv->partitions.count || !priv->partitions.descs) {
+		log_err("[FFA] no partition installed\n");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		log_err("[FFA] no UUID provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_count) {
+		log_err("[FFA] no size/count provided\n");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		log_err("[FFA] invalid UUID\n");
+		return -EINVAL;
+	}
+
+	if (!buffer) {
+		/* Mode 1: getting the number of secure partitions */
+
+		fill_data = 0;
+
+		log_info("[FFA] Preparing for checking partitions count\n");
+
+	} else if (*sp_count) {
+		/* Mode 2: retrieving the partitions information */
+
+		fill_data = 1;
+
+		client_desc_idx = 0;
+
+		log_info("[FFA] Preparing for filling partitions info\n");
+
+	} else {
+		log_err("[FFA] invalid function arguments provided\n");
+		return -EINVAL;
+	}
+
+	log_info("[FFA] Searching partitions using the provided UUID\n");
+
+	/* Search in the cached partitions */
+	for (desc_idx = 0;
+	     desc_idx < priv->partitions.count;
+	     desc_idx++) {
+		if (ffa_uuid_are_identical(&priv->partitions.descs[desc_idx].sp_uuid,
+					   &part_uuid)) {
+			log_info("[FFA] Partition ID %x matches the provided UUID\n",
+				 priv->partitions.descs[desc_idx].info.id);
+
+			sp_found++;
+
+			if (fill_data) {
+				/* Trying to fill the partition info in the input buffer */
+
+				if (client_desc_idx < *sp_count) {
+					buffer[client_desc_idx++] =
+						priv->partitions.descs[desc_idx].info;
+					continue;
+				}
+
+				log_err("[FFA] failed to fill client descriptor, buffer full\n");
+				return -ENOBUFS;
+			}
+		}
+	}
+
+	if (!sp_found) {
+		int ret;
+
+		log_info("[FFA] No partition found. Querying framework ...\n");
+
+		ret = ffa_query_partitions_info(dev, &part_uuid, &sp_found);
+
+		if (ret == 0) {
+			if (!fill_data) {
+				*sp_count = sp_found;
+
+				log_info("[FFA] Number of partition(s) matching the UUID: %d\n",
+					 sp_found);
+			} else {
+				/*
+				 * If SPs data detected, they are already in the private data
+				 * structure, retry searching SP data again to return them
+				 *  to the caller
+				 */
+				if (sp_found)
+					ret = ffa_get_partitions_info_hdlr(dev, uuid_str, sp_count,
+									   buffer);
+				else
+					ret = -ENODATA;
+			}
+		}
+
+		return ret;
+	}
+
+	/* Partition(s) found */
+	if (!fill_data)
+		*sp_count = sp_found;
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info() - Queries and saves all secure partitions data
+ * @dev: The FF-A bus device
+ *
+ * This function invokes FFA_PARTITION_INFO_GET FF-A
+ * function to query from secure world all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in the
+ * resident private data structure and we keep the UUID field empty
+ * (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * This function is called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(struct udevice *dev)
+{
+	return ffa_query_partitions_info(dev, NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u64 req_mode, resp_mode;
+	struct ffa_priv *priv = NULL;
+
+	if (!dev)
+		return -ENODEV;
+
+	priv = dev_get_priv(dev);
+
+	if (!priv || !priv->dscvry_info.invoke_ffa_fn)
+		return -EINVAL;
+
+	/* No partition installed */
+	if (!priv->partitions.count || !priv->partitions.descs)
+		return -ENODEV;
+
+	if (is_smc64) {
+		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+	} else {
+		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
+	}
+
+	priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = req_mode,
+			.a1 = PREP_SELF_ENDPOINT_ID(priv->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == resp_mode) {
+		/* Message sent with response extract the return data */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/* FF-A driver operations (used by clients for communicating with FF-A)*/
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ *
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of partitions
+ *			 The variable will be set by the driver
+ *	@buffer: NULL
+ *
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@dev: The FF-A bus device
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of empty partition descriptors
+ *			 The variable will be read by the driver
+ *	@buffer: pointer to SPs information buffer
+ *		(allocated by the client and contains empty @sp_count descriptors).
+ *		The buffer will be filled by the driver
+ *
+ * Driver operation for FFA_PARTITION_INFO_GET.
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * @sp_count: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer size, the buffer will be
+ * filled by the driver.
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_info *buffer)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->partition_info_get)
+		return -ENOSYS;
+
+	return ops->partition_info_get(dev, uuid_str, sp_count, buffer);
+}
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Driver operation for FFA_MSG_SEND_DIRECT_{REQ,RESP}.
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->sync_send_receive)
+		return -ENOSYS;
+
+	return ops->sync_send_receive(dev, dst_part_id, msg, is_smc64);
+}
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * @dev: The FF-A bus device
+ *
+ * Driver operation for FFA_RXTX_UNMAP.
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_rxtx_unmap(struct udevice *dev)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->rxtx_unmap)
+		return -ENOSYS;
+
+	return ops->rxtx_unmap(dev);
+}
+
+/* Implementation of FF-A bus discovery and initial setup */
+
+/**
+ * ffa_try_discovery() - performs FF-A discovery
+ * Tries 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:
+ *
+ * true on success. Otherwise, false.
+ */
+bool ffa_try_discovery(void)
+{
+	int ret;
+
+	log_info("[FFA] trying FF-A framework discovery\n");
+
+	ret = ffa_set_smc_conduit();
+	if (ret)
+		return false;
+
+	ret = ffa_get_version_hdlr();
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/**
+ * ffa_devm_alloc_priv() - allocate FF-A driver private data
+ * @dev:	the FF-A bus device (arm_ffa)
+ * @priv: Pointer to the FF-A bus private data
+ *
+ * This function dynamically allocates with devres the private data structure
+ * which contains all the FF-A data.
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_devm_alloc_priv(struct udevice *dev, struct ffa_priv **priv)
+{
+	if (!priv)
+		return -EINVAL;
+
+	*priv = devm_kmalloc(dev, sizeof(struct ffa_priv), __GFP_ZERO);
+	if (!(*priv)) {
+		log_err("[FFA] can not allocate FF-A main data structure\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_do_probe() - probing FF-A framework
+ * @dev:	the FF-A bus device (arm_ffa)
+ *
+ * Probing is triggered on demand by clients searching for the uclass.
+ * At probe level the following actions are done:
+ *	- allocating private data (priv) with devres
+ *	- updating priv with discovery information
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in the private data structure (priv).
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_do_probe(struct udevice *dev)
+{
+	int ret;
+	struct ffa_priv *priv;
+
+	ret = ffa_devm_alloc_priv(dev, &priv);
+	if (ret)
+		return ret;
+
+	/* register the structure with the DM */
+	dev_set_priv(dev, priv);
+
+	priv->dscvry_info = dscvry_info;
+
+	ret = ffa_get_endpoint_id(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_cache_partitions_info(dev);
+	if (ret) {
+		ffa_unmap_rxtx_buffers_hdlr(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_do_remove() - FF-A cleanup at device removal
+ * @dev:	the FF-A device
+ * Making sure the RX/TX buffers are unmapped and freed when the device is removed.
+ * No need to free the private data structure because devres takes care of that.
+ * Return:
+ *
+ * 0 on success.
+ */
+int ffa_do_remove(struct udevice *dev)
+{
+	log_info("[FFA] removing the device\n");
+
+	ffa_unmap_rxtx_buffers_hdlr(dev);
+	dev_set_priv(dev, NULL);
+
+	return 0;
+}
+
+/**
+ * ffa_unbind() - FF-A cleanup at device unbinding
+ * @dev:	the FF-A device
+ * Making sure the RX/TX buffers are unmapped and freed when the device is unbound.
+ * No need to free the private data structure because devres takes care of that.
+ * Return:
+ *
+ * 0 on success.
+ */
+int ffa_do_unbind(struct udevice *dev)
+{
+	struct ffa_priv *priv = dev_get_priv(dev);
+
+	log_info("[FFA] unbinding the device\n");
+
+	if (priv)
+		ffa_unmap_rxtx_buffers_hdlr(dev);
+
+	return 0;
+}
+
+UCLASS_DRIVER(ffa) = {
+	.name		= "ffa",
+	.id		= UCLASS_FFA,
+};
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
new file mode 100644
index 0000000000..cf19926e52
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -0,0 +1,148 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <linux/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * ffa_bus_is_supported() - FF-A discovery callback
+ * @invoke_fn: legacy SMC invoke function (not used)
+ *
+ * This function performs FF-A discovery by calling ffa_try_discovery().
+ * Discovery is performed by querying the FF-A framework version from
+ * secure world using the FFA_VERSION ABI.
+ *
+ * The FF-A driver is registered as an SMCCC feature driver. So, features discovery
+ * callbacks are called by the PSCI driver (PSCI device is the SMCCC features
+ * root device).
+ *
+ * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
+ * So, the legacy SMC invocation is not used.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static bool ffa_bus_is_supported(void (*invoke_fn)(ulong a0, ulong a1,
+						   ulong a2, ulong a3,
+						   ulong a4, ulong a5,
+						   ulong a6, ulong a7,
+						   struct arm_smccc_res *res))
+{
+	return ffa_try_discovery();
+}
+
+/**
+ * __arm_ffa_fn_smc() - 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 low level SMC assembly function
+ */
+void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * ffa_set_smc_conduit() - Set the SMC conduit
+ *
+ * Selects the SMC conduit by setting the FF-A ABI invoke function
+ * to the function executing the SMC call.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_set_smc_conduit(void)
+{
+	dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc;
+	log_info("[FFA] Using Arm SMC for FF-A conduit\n");
+
+	return 0;
+}
+
+/**
+ * ffa_probe() - The Arm FF-A driver probe function
+ * @dev:	the FF-A bus device (arm_ffa)
+ *
+ * Probing is done through ffa_do_probe()
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_probe(struct udevice *dev)
+{
+	return ffa_do_probe(dev);
+}
+
+/**
+ * ffa_remove() - The driver remove function
+ * @dev:	the arm_ffa device
+ *
+ * FF-A cleanup.
+ *
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_remove(struct udevice *dev)
+{
+	return ffa_do_remove(dev);
+}
+
+/**
+ * ffa_unbind() - The driver unbind function
+ * @dev:	the arm_ffa device
+ *
+ * FF-A cleanup.
+ *
+ * Return:
+ *
+ * 0 on success.
+ */
+static int ffa_unbind(struct udevice *dev)
+{
+	return ffa_do_unbind(dev);
+}
+
+/* Arm FF-A driver operations */
+
+static const struct ffa_bus_ops 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,
+};
+
+/* Registering the FF-A driver as an SMCCC feature driver */
+
+ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
+	.driver_name = FFA_DRV_NAME,
+	.is_supported = ffa_bus_is_supported,
+};
+
+/* Declaring the FF-A driver under UCLASS_FFA */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.flags		= DM_REMOVE_OS_PREPARE,
+	.probe		= ffa_probe,
+	.remove	= ffa_remove,
+	.unbind	= ffa_unbind,
+	.ops		= &ffa_ops,
+};
diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
new file mode 100644
index 0000000000..4338f9c9b1
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
@@ -0,0 +1,14 @@
+/* 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/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..e327f786c3
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,269 @@
+/* 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 __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct ffa_send_direct_data {
+	ulong data0; /* w3/x3 */
+	ulong data1; /* w4/x4 */
+	ulong data2; /* w5/x5 */
+	ulong data3; /* w6/x6 */
+	ulong data4; /* w7/x7 */
+};
+
+/* FF-A discovery information */
+extern struct ffa_discovery_info dscvry_info;
+
+struct udevice;
+
+/**
+ * struct ffa_bus_ops - Operations for FF-A
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
+				  u32 *sp_count, struct ffa_partition_info *buffer);
+	int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg,
+				 bool is_smc64);
+	int (*rxtx_unmap)(struct udevice *dev);
+};
+
+#define ffa_get_ops(dev)        ((struct ffa_bus_ops *)(dev)->driver->ops)
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ */
+int ffa_rxtx_unmap(struct udevice *dev);
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The arm_ffa bus device
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev);
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The arm_ffa bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_info *buffer);
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of partitions
+ *			 The variable will be set by the driver
+ *	@buffer: NULL
+ *
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@dev: The arm_ffa bus device
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of empty partition descriptors
+ *			 The variable will be read by the driver
+ *	@buffer: pointer to SPs information buffer
+ *		(allocated by the client and contains empty @sp_count descriptors).
+ *		The buffer will be filled by the driver
+ *
+ * This function queries the secure partition data from
+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * When invoked through a client request, ffa_get_partitions_info_hdlr() should be
+ * called twice. First call is to get from the driver the number of secure
+ * partitions (SPs) associated to a particular UUID.
+ * Then, the caller (client) allocates the buffer to host the SPs data and
+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
+ * buffer.
+ *
+ * To achieve the mechanism described above, ffa_get_partitions_info_hdlr() uses the
+ * following functions:
+ *		ffa_read_partitions_info
+ *		ffa_query_partitions_info
+ *
+ * Return:
+ *
+ * @sp_count: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer size, the buffer will be
+ * filled by the driver.
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_info *buffer);
+
+struct ffa_priv;
+
+/**
+ * ffa_do_probe() - probing FF-A framework
+ * @dev:	the FF-A bus device (arm_ffa)
+ *
+ * Probing is triggered on demand by clients searching for the uclass.
+ * At probe level the following actions are done:
+ *	- allocating private data (priv) with devres
+ *	- updating priv with discovery information
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in the private data structure (priv).
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_do_probe(struct udevice *dev);
+
+/**
+ * ffa_do_remove() - FF-A cleanup at device removal
+ * @dev:	the FF-A device
+ * Making sure the RX/TX buffers are unmapped and freed when the device is removed.
+ * No need to free the private data structure because devres takes care of that.
+ * Return:
+ *
+ * 0 on success.
+ */
+int ffa_do_remove(struct udevice *dev);
+
+/**
+ * ffa_unbind() - FF-A cleanup at device unbinding
+ * @dev:	the FF-A device
+ * Making sure the RX/TX buffers are unmapped and freed when the device is unbound.
+ * No need to free the private data structure because devres takes care of that.
+ * Return:
+ *
+ * 0 on success.
+ */
+int ffa_do_unbind(struct udevice *dev);
+
+/**
+ * ffa_set_smc_conduit() - Set the SMC conduit
+ *
+ * Selects the SMC conduit by setting the FF-A ABI invoke function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_set_smc_conduit(void);
+
+/**
+ * ffa_try_discovery() - performs FF-A discovery
+ * Tries 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:
+ *
+ * true on success. Otherwise, false.
+ */
+bool ffa_try_discovery(void);
+
+#endif
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
new file mode 100644
index 0000000000..a7b60b1aa2
--- /dev/null
+++ b/include/arm_ffa_priv.h
@@ -0,0 +1,254 @@
+/* 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 __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <mapmem.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+
+/* This header is exclusively used by the FF-A Uclass and FF-A Arm driver */
+
+/* Arm FF-A driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* The FF-A SMC function definitions */
+
+#if CONFIG_IS_ENABLED(SANDBOX)
+
+/* Providing Arm SMCCC declarations to sandbox */
+
+/**
+ * struct sandbox_smccc_1_2_regs - emulated SMC call arguments or results
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct sandbox_smccc_1_2_regs {
+	ulong a0;
+	ulong a1;
+	ulong a2;
+	ulong a3;
+	ulong a4;
+	ulong a5;
+	ulong a6;
+	ulong a7;
+	ulong a8;
+	ulong a9;
+	ulong a10;
+	ulong a11;
+	ulong a12;
+	ulong a13;
+	ulong a14;
+	ulong a15;
+	ulong a16;
+	ulong a17;
+};
+
+typedef struct sandbox_smccc_1_2_regs ffa_value_t;
+
+#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))
+
+#else
+/* CONFIG_ARM64 */
+#include <linux/arm-smccc.h>
+typedef struct arm_smccc_1_2_regs ffa_value_t;
+#endif
+
+/* Defining the function pointer type for the function executing the FF-A ABIs */
+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)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR                 = 0x60,
+	FFA_SUCCESS               = 0x61,
+	FFA_INTERRUPT             = 0x62,
+	FFA_VERSION               = 0x63,
+	FFA_FEATURES              = 0x64,
+	FFA_RX_RELEASE            = 0x65,
+	FFA_RXTX_MAP              = 0x66,
+	FFA_RXTX_UNMAP            = 0x67,
+	FFA_PARTITION_INFO_GET    = 0x68,
+	FFA_ID_GET                = 0x69,
+	FFA_RUN                   = 0x6d,
+	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
+	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
+
+	/* To be updated when adding new FFA IDs */
+	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
+	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
+};
+
+enum ffa_abi_errcode {
+	NOT_SUPPORTED = 1,
+	INVALID_PARAMETERS,
+	NO_MEMORY,
+	BUSY,
+	INTERRUPTED,
+	DENIED,
+	RETRY,
+	ABORTED,
+	MAX_NUMBER_FFA_ERR
+};
+
+extern int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR];
+
+/* Container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
+
+/*
+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
+ * @a1-4:	32-bit words access to the UUID data
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Hosts the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	void *rxbuf; /* Virtual address returned by memalign */
+	void *txbuf; /* Virtual address returned by memalign */
+	size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * Contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* Virtual address */
+};
+
+/**
+ * struct ffa_discovery_info - discovery information
+ * @fwk_version:	FF-A framework version
+ * @invoke_ffa_fn:	The function executing the FF-A function (ABI)
+ */
+struct ffa_discovery_info {
+	u32 fwk_version;
+	invoke_ffa_fn_t invoke_ffa_fn;
+};
+
+/**
+ * struct ffa_priv - the driver private data structure
+ *
+ * @dscvry_info:	Initial information discovered
+ * @ops:	The driver operations structure
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ *
+ * The device private data structure containing all the
+ * data read from secure world.
+ * The data is dynamically allocated, managed by devres
+ * and registered with the DM.
+ */
+struct ffa_priv {
+	struct ffa_discovery_info dscvry_info;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+};
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 33e43c20db..df77c7da58 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,11 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -55,6 +60,7 @@ enum uclass_id {
 	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v10 05/10] arm_ffa: introduce armffa command
  2023-03-28 16:11                                                                                       ` [PATCH v10 " Abdellatif El Khlifi
                                                                                                           ` (3 preceding siblings ...)
  2023-03-28 16:11                                                                                         ` [PATCH v10 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-03-28 16:11                                                                                         ` Abdellatif El Khlifi
  2023-04-02  2:40                                                                                           ` Simon Glass
  2023-03-28 16:11                                                                                         ` [PATCH v10 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
                                                                                                           ` (5 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-28 16:11 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong, Heinrich Schuchardt

Provide armffa command showcasing the use of the U-Boot FF-A support

armffa is a command showcasing how to invoke FF-A operations.
This provides a guidance to the client developers on how to
call the FF-A bus interfaces. The command also allows to gather secure
partitions information and ping these  partitions. The command is also
helpful in testing the communication with secure partitions.

For more details please refer to the command documentation [1].

[1]: doc/usage/cmd/armffa.rst

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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

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

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* address nits

v9:

* remove manual FF-A discovery and use DM
* use DM class APIs to probe and interact with the FF-A bus
* add doc/usage/cmd/armffa.rst

v8:

* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* adapt do_ffa_dev_list() following the recent update on
  uclass_first_device/uclass_next_device functions (they return void now)
* set armffa command to use 64-bit direct messaging

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

 MAINTAINERS                      |   2 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   2 +
 cmd/armffa.c                     | 238 +++++++++++++++++++++++++++++++
 doc/arch/arm64.ffa.rst           |   7 +
 doc/usage/cmd/armffa.rst         | 107 ++++++++++++++
 doc/usage/index.rst              |   1 +
 drivers/firmware/arm-ffa/Kconfig |   1 +
 8 files changed, 368 insertions(+)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/usage/cmd/armffa.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 62c30184bb..add208e4ef 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,7 +269,9 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+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
diff --git a/cmd/Kconfig b/cmd/Kconfig
index ba5ec69293..b814a20d8a 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -934,6 +934,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the FF-A support
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index d95833b2de..a1eb45f881 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,8 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
 obj-$(CONFIG_CMD_AES) += aes.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..d983a23bbc
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,238 @@
+// 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 <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+#include <asm/io.h>
+
+/**
+ * do_ffa_getpart() - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver partition_info_get operation
+ * which implements FFA_PARTITION_INFO_GET ABI to retrieve the data.
+ * The input UUID string is expected to be in big endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx;
+	struct udevice *dev = NULL;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	uclass_first_device(UCLASS_FFA, &dev);
+	if (!dev) {
+		log_err("[FFA][CMD] Cannot find FF-A bus device\n");
+		return -ENODEV;
+	}
+
+	/* Mode 1: getting the number of secure partitions */
+	ret = ffa_partition_info_get(dev, argv[0], &count, NULL);
+	if (ret) {
+		log_err("[FFA][CMD] Failure in querying partitions count (error code: %d)\n", ret);
+		return ret;
+	}
+
+	if (!count) {
+		log_info("[FFA][CMD] No secure partition found\n");
+		return ret;
+	}
+
+	/*
+	 * Pre-allocate a buffer to be filled by the driver
+	 * with ffa_partition_info structs
+	 */
+
+	log_info("[FFA][CMD] Pre-allocating %d partition(s) info structures\n", count);
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return -EINVAL;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+
+	ret = ffa_partition_info_get(dev, argv[0], &count, parts_info);
+	if (ret) {
+		log_err("[FFA][CMD] Failure in querying partition(s) info (error code: %d)\n", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/* SPs found , show the partition information */
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		log_info("[FFA][CMD] Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x\n",
+			 parts_info[info_idx].id,
+			 parts_info[info_idx].exec_ctxt,
+			 parts_info[info_idx].properties);
+	}
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * do_ffa_ping() - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function sends data to the secure partition which the ID is provided
+ * as an argument. The function uses the arm_ffa driver sync_send_receive operation
+ * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+	struct udevice *dev = NULL;
+
+	if (argc != 1)
+		return -EINVAL;
+
+	errno = 0;
+	part_id = strtoul(argv[0], NULL, 16);
+
+	if (errno) {
+		log_err("[FFA][CMD] Invalid partition ID\n");
+		return -EINVAL;
+	}
+
+	uclass_first_device(UCLASS_FFA, &dev);
+	if (!dev) {
+		log_err("[FFA][CMD] Cannot find FF-A bus device\n");
+		return -ENODEV;
+	}
+
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	if (!ret) {
+		u8 cnt;
+
+		log_info("[FFA][CMD] SP response:\n[LSB]\n");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			log_info("[FFA][CMD] 0x%llx\n", ((u64 *)&msg)[cnt]);
+	} else {
+		log_err("[FFA][CMD] Sending direct request error (%d)\n", ret);
+	}
+
+	return ret;
+}
+
+/**
+ *do_ffa_devlist() - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function queries the device belonging to the UCLASS_FFA
+ * class.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev = NULL;
+
+	uclass_first_device(UCLASS_FFA, &dev);
+	if (!dev) {
+		log_err("[FFA][CMD] Cannot find FF-A bus device\n");
+		return -ENODEV;
+	}
+
+	log_info("[FFA][CMD] device name %s, dev %08x, driver name %s, ops %08x\n",
+		 dev->name,
+		 (u32)map_to_sysmem(dev),
+		 dev->driver->name,
+		 (u32)map_to_sysmem(dev->driver->ops));
+
+	return 0;
+}
+
+static struct cmd_tbl armffa_commands[] = {
+	U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_getpart, "", ""),
+	U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_ping, "", ""),
+	U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_devlist, "", ""),
+};
+
+/**
+ * do_armffa() - the armffa command main function
+ * @cmdtp:	Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * This function identifies which armffa subcommand to run.
+ * Then, it makes sure the arm_ffa device is probed and
+ * ready for use.
+ * Then, it runs the subcommand.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct cmd_tbl *armffa_cmd;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
+
+	argc -= 2;
+	argv += 2;
+
+	if (!armffa_cmd || argc > armffa_cmd->maxargs)
+		return CMD_RET_USAGE;
+
+	ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
+
+	return cmd_process_error(armffa_cmd, ret);
+}
+
+U_BOOT_CMD(armffa, 4, 1, do_armffa,
+	   "Arm FF-A operations test command",
+	   "getpart <partition UUID>\n"
+	   "	 - lists the partition(s) info\n"
+	   "ping <partition ID>\n"
+	   "	 - sends a data pattern to the specified partition\n"
+	   "devlist\n"
+	   "	 - displays information about the FF-A device/driver\n");
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index ddf6435402..5fedb0c255 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -218,6 +218,13 @@ The following features are provided:
 
 - FF-A bus can be compiled and used without EFI
 
+The armffa command
+-----------------------------------
+
+armffa is an implementation defined command showcasing how to use the FF-A bus and how to invoke the driver operations.
+
+Please refer the command documentation at doc/usage/cmd/armffa.rst
+
 Example of boot logs with FF-A enabled
 --------------------------------------
 
diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
new file mode 100644
index 0000000000..9bf59e393b
--- /dev/null
+++ b/doc/usage/cmd/armffa.rst
@@ -0,0 +1,107 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+armffa command
+==============
+
+Synopsis
+--------
+
+::
+
+   armffa [sub-command] [arguments]
+
+   sub-commands:
+
+        getpart [partition UUID]
+
+            lists the partition(s) info
+
+        ping [partition ID]
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays information about the FF-A device/driver
+
+Description
+-----------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
+
+The command also allows to gather secure partitions information and ping these  partitions.
+
+The command is also helpful in testing the communication with secure partitions.
+
+Example
+-------
+
+The following examples are run on Corstone-1000 platform with debug logs enabled.
+
+* ping
+
+::
+
+   corstone1000# armffa ping 0x8003
+   [FFA][CMD] SP response:
+   [LSB]
+   [FFA][CMD] 0xfffffffe
+   [FFA][CMD] 0x0
+   [FFA][CMD] 0x0
+   [FFA][CMD] 0x0
+   [FFA][CMD] 0x0
+
+* ping (failure case)
+
+::
+
+   corstone1000# armffa ping 0x8009
+   [FFA][CMD] Sending direct request error (-22)
+   Command 'ping' failed: Error -22
+
+* getpart
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
+   [FFA] Preparing for checking partitions count
+   [FFA] Searching partitions using the provided UUID
+   [FFA] No partition found. Querying framework ...
+   [FFA] Reading partitions data from the RX buffer
+   [FFA] Number of partition(s) matching the UUID: 1
+   [FFA][CMD] Pre-allocating 1 partition(s) info structures
+   [FFA] Preparing for filling partitions info
+   [FFA] Searching partitions using the provided UUID
+   [FFA] Partition ID 8003 matches the provided UUID
+   [FFA][CMD] Partition: id = 0x8003 , exec_ctxt 0x1 , properties 0x3
+
+* getpart (failure case)
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7228
+   [FFA] Preparing for checking partitions count
+   [FFA] Searching partitions using the provided UUID
+   [FFA] No partition found. Querying framework ...
+   [FFA] INVALID_PARAMETERS: Unrecognized UUID
+   [FFA][CMD] Failure in querying partitions count (error code: -22)
+   Command 'getpart' failed: Error -22
+
+* devlist
+
+::
+
+   corstone1000# armffa devlist
+   [FFA][CMD] device name arm_ffa, dev fdf41c30, driver name arm_ffa, ops fffc0fc8
+
+Configuration
+-------------
+
+The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
+
+Return value
+------------
+
+The return value $? is 0 (true) on success and a negative error code on failure.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index bc85e1d49a..df107fb710 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -21,6 +21,7 @@ Shell commands
 
    cmd/acpi
    cmd/addrmap
+   cmd/armffa
    cmd/askenv
    cmd/base
    cmd/bdinfo
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index 9200c8028b..a7d5392859 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
 	depends on DM && ARM64
 	select ARM_SMCCC
 	select ARM_SMCCC_FEATURES
+	imply CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v10 06/10] arm_ffa: introduce sandbox FF-A support
  2023-03-28 16:11                                                                                       ` [PATCH v10 " Abdellatif El Khlifi
                                                                                                           ` (4 preceding siblings ...)
  2023-03-28 16:11                                                                                         ` [PATCH v10 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-03-28 16:11                                                                                         ` Abdellatif El Khlifi
  2023-04-02  2:41                                                                                           ` Simon Glass
  2023-03-28 16:11                                                                                         ` [PATCH v10 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                                                                           ` (4 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-28 16:11 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong, Heinrich Schuchardt

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>
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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

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

v10:

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

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

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

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

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

v1: introduce the sandbox driver

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

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


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v10 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA
  2023-03-28 16:11                                                                                       ` [PATCH v10 " Abdellatif El Khlifi
                                                                                                           ` (5 preceding siblings ...)
  2023-03-28 16:11                                                                                         ` [PATCH v10 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
@ 2023-03-28 16:11                                                                                         ` Abdellatif El Khlifi
  2023-04-02  2:40                                                                                           ` Simon Glass
  2023-03-28 16:11                                                                                         ` [PATCH v10 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                                                                           ` (3 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-28 16:11 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong, Heinrich Schuchardt

Add functional test cases for the FF-A support

These tests rely on the FF-A sandbox emulator and FF-A
sandbox driver which help in inspecting the FF-A communication.

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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

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

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT
* address nits

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

v8:

  * update partition_info_get() second argument to be an SP count
  * pass NULL device pointer to the FF-A bus discovery and operations

v7: set the tests to use 64-bit direct messaging

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

v1: introduce sandbox tests

 MAINTAINERS            |   1 +
 doc/arch/arm64.ffa.rst |   1 +
 test/dm/Makefile       |   2 +
 test/dm/ffa.c          | 357 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 361 insertions(+)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index b8019517ba..8f698b3f20 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 457a0e112e..5b1450f579 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -38,6 +38,7 @@ The U-Boot FF-A support provides the following parts:
   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.
+- Sandbox FF-A test cases.
 
 FF-A and SMC specifications
 -------------------------------------------
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 7a79b6e1a2..45563bdfb4 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -85,6 +86,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..d493597521
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,357 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <console.h>
+#include <dm.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <asm/sandbox_arm_ffa_priv.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Macros */
+
+#define LOG_MSG_SZ (100)
+#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
+
+/* Functional tests for the UCLASS_FFA */
+
+static int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
+{
+	char cmd[LOG_CMD_SZ] = {0};
+
+	console_record_reset();
+
+	snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
+	run_command(cmd, 0);
+
+	ut_assert_console_end();
+
+	return 0;
+}
+
+static int check_fwk_version(struct ffa_priv *priv, struct unit_test_state *uts)
+{
+	struct ffa_sandbox_data func_data;
+	u32 fwk_version = 0;
+
+	func_data.data0 = &fwk_version;
+	func_data.data0_size = sizeof(fwk_version);
+	ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION, &func_data));
+
+	if (priv->dscvry_info.fwk_version != fwk_version) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: framework version: core = 0x%x , sandbox  = 0x%x", __func__,
+			 priv->dscvry_info.fwk_version,
+			 fwk_version);
+
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return 0;
+}
+
+static int check_endpoint_id(struct ffa_priv *priv, struct unit_test_state *uts)
+{
+	if (priv->id) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ,
+			 "[%s]: Error: endpoint id: core = 0x%x", __func__, priv->id);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return 0;
+}
+
+static int check_rxtxbuf(struct ffa_priv *priv, struct unit_test_state *uts)
+{
+	if (!priv->pair.rxbuf || !priv->pair.txbuf) {
+		char msg[LOG_MSG_SZ] = {0};
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = %p txbuf = %p", __func__,
+			 priv->pair.rxbuf,
+			 priv->pair.txbuf);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return 0;
+}
+
+static int check_features(struct ffa_priv *priv, struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	if (priv->pair.rxtx_min_pages != RXTX_4K &&
+	    priv->pair.rxtx_min_pages != RXTX_16K &&
+	    priv->pair.rxtx_min_pages != RXTX_64K) {
+		snprintf(msg,
+			 LOG_MSG_SZ,
+			 "[%s]: Error: FFA_RXTX_MAP features = 0x%lx",
+			 __func__,
+			 priv->pair.rxtx_min_pages);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+
+	return 0;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	char msg[LOG_MSG_SZ] = {0};
+
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+		if (rxbuf_mapped)
+			return 0;
+		break;
+	case FFA_RXTX_UNMAP:
+		if (!rxbuf_mapped)
+			return 0;
+		break;
+	default:
+		return CMD_RET_FAILURE;
+	}
+
+	snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__,
+		 (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP"));
+	dm_test_ffa_log(uts, msg);
+
+	return CMD_RET_FAILURE;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	if (rxbuf_owned) {
+		char msg[LOG_MSG_SZ];
+
+		snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__);
+		dm_test_ffa_log(uts, msg);
+		return CMD_RET_FAILURE;
+	}
+	return 0;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg;
+	u8 cnt;
+	struct udevice *dev;
+
+	uclass_first_device(UCLASS_FFA, &dev);
+	ut_assertnonnull(dev);
+
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]);
+
+	return 0;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct unit_test_state *uts)
+{
+	u32 count;
+	struct ffa_partition_info *parts_info;
+	u32 info_idx, exp_info_idx;
+	int ret;
+	struct udevice *dev;
+	struct ffa_sandbox_data func_data;
+	struct ffa_partitions *partitions;
+
+	uclass_first_device(UCLASS_FFA, &dev);
+	ut_assertnonnull(dev);
+
+	/* Get from the driver the count of the SPs matching the UUID */
+	ret = ffa_partition_info_get(dev, service_uuid, &count, NULL);
+	/* Make sure partitions are detected */
+	ut_assertok(ret);
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+
+	/* Pre-allocate a buffer to be filled by the driver with ffa_partition_info structs */
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	ut_assertnonnull(parts_info);
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ret = ffa_partition_info_get(dev, service_uuid, &count, parts_info);
+	if (ret != 0) {
+		free(parts_info);
+		ut_assertok(ret);
+	}
+
+	/* SPs found , verify the partitions information */
+
+	func_data.data0 = &partitions;
+	func_data.data0_size = sizeof(struct ffa_partitions *);
+	ut_assertok(sandbox_ffa_query_core_state(FFA_PARTITION_INFO_GET, &func_data));
+
+	ret = CMD_RET_FAILURE;
+
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		for (exp_info_idx = 0;
+		     exp_info_idx < partitions->count;
+		     exp_info_idx++) {
+			if (parts_info[info_idx].id ==
+			   partitions->descs[exp_info_idx].info.id) {
+				ret = memcmp(&parts_info[info_idx],
+					     &partitions->descs[exp_info_idx]
+					     .info,
+					     sizeof(struct ffa_partition_info));
+				if (ret)
+					free(parts_info);
+				ut_assertok(ret);
+				/* Send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
+			}
+			ret = 0;
+		}
+	}
+
+	free(parts_info);
+
+	/* Verify expected partitions found in the emulated secure world */
+	ut_assertok(ret);
+
+	return 0;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_priv *priv;
+	struct ffa_sandbox_data func_data;
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	int ret;
+	struct udevice *dev;
+
+	/* Test probing the sandbox FF-A bus */
+	uclass_first_device(UCLASS_FFA, &dev);
+	ut_assertnonnull(dev);
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	priv = dev_get_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(priv);
+
+	/* Test FFA_VERSION */
+	ut_assertok(check_fwk_version(priv, uts));
+
+	/* Test FFA_ID_GET */
+	ut_assertok(check_endpoint_id(priv, uts));
+
+	/* Test FFA_FEATURES */
+	ut_assertok(check_features(priv, uts));
+
+	/*  Test core RX/TX buffers */
+	ut_assertok(check_rxtxbuf(priv, uts));
+
+	/* Test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_MAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc1_uuid, uts);
+	ut_assertok(ret);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	ret = test_partitions_and_comms(svc2_uuid, uts);
+	ut_assertok(ret);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RX_RELEASE, &func_data));
+	ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts));
+
+	/* Test FFA_RXTX_UNMAP */
+	ut_assertok(ffa_rxtx_unmap(dev));
+
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_ffa_query_core_state(FFA_RXTX_UNMAP, &func_data));
+	ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts));
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_priv *priv;
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg;
+	int ret;
+	u32 count = 0;
+	u16 part_id = 0;
+	struct udevice *dev;
+
+	/* Test probing the sandbox FF-A bus */
+	uclass_first_device(UCLASS_FFA, &dev);
+	ut_assertnonnull(dev);
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	priv = dev_get_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(priv);
+
+	/* Query partitions count using  invalid arguments */
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID  string */
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid_str, &count, NULL);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, NULL);
+	ut_assertok(count);
+
+	/* Query partitions count using a valid UUID */
+	count = 0;
+	ret = ffa_partition_info_get(dev, valid_svc_uuid, &count, NULL);
+	/* Make sure partitions are detected */
+	ut_assertok(ret);
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+
+	/* Send data to an invalid partition */
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Send data to a valid partition */
+	part_id = priv->partitions.descs[0].info.id;
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	ut_assertok(ret);
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v10 08/10] arm_ffa: introduce armffa command Sandbox test
  2023-03-28 16:11                                                                                       ` [PATCH v10 " Abdellatif El Khlifi
                                                                                                           ` (6 preceding siblings ...)
  2023-03-28 16:11                                                                                         ` [PATCH v10 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-03-28 16:11                                                                                         ` Abdellatif El Khlifi
  2023-03-28 16:11                                                                                         ` [PATCH v10 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
                                                                                                           ` (2 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-28 16:11 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

Add Sandbox test for the armffa command

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
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>

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

v10:

* replace CMD_RET_SUCCESS with 0
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT

v9: align the test with FF-A discovery through DM

v4: drop use of helper APIs

v1: introduce armffa command sandbox test

 MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 39 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 8f698b3f20..9019370d71 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 7848f348bc..8d0ec038cd 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -20,6 +21,7 @@ obj-$(CONFIG_CMD_SEAMA) += seama.o
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_CMD_READ) += rw.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o
 endif
 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
 obj-$(CONFIG_CMD_WGET) += wget.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..a9768dbd2c
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * 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 <string.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define PING_CMD_SIZE 19
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	char ping_cmd[PING_CMD_SIZE] = {0};
+
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	snprintf(ping_cmd, PING_CMD_SIZE, "armffa ping 0x%x", SANDBOX_SP1_ID);
+
+	/* armffa ping <ID> */
+	ut_assertok(run_command(ping_cmd, 0));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return 0;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v10 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-03-28 16:11                                                                                       ` [PATCH v10 " Abdellatif El Khlifi
                                                                                                           ` (7 preceding siblings ...)
  2023-03-28 16:11                                                                                         ` [PATCH v10 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2023-03-28 16:11                                                                                         ` Abdellatif El Khlifi
  2023-03-31  8:29                                                                                           ` Ilias Apalodimas
  2023-03-28 16:11                                                                                         ` [PATCH v10 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-28 16:11 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong, Gowtham Suresh Kumar

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

MM communication protocol supports FF-A 64-bit direct messaging.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>

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

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* addressing nits

v9: align how FF-A is used with FF-A discovery through DM

v8:

* isolate the compilation choices between FF-A and OP-TEE
* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make mm_sp_svc_uuid static
* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
* improve use of unmap_sysmem() in ffa_mm_communicate()

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

 include/mm_communication.h        |   6 +
 lib/efi_loader/Kconfig            |  14 +-
 lib/efi_loader/efi_variable_tee.c | 300 +++++++++++++++++++++++++++++-
 3 files changed, 314 insertions(+), 6 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..87509fec3f 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,9 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *    Authors:
+ *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +16,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c5835e6ef6..08a6b84101 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	depends on OPTEE || ARM_FFA_TRANSPORT
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..a3060b4e7e 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,9 +4,14 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  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 <efi.h>
 #include <efi_api.h>
 #include <efi_loader.h>
@@ -15,6 +20,36 @@
 #include <malloc.h>
 #include <mm_communication.h>
 
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+#include <arm_ffa.h>
+#include <cpu_func.h>
+#include <mapmem.h>
+
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_SIZE 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_OFFSET
+#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_OFFSET 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_ADDR 0
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+
+static const char *mm_sp_svc_uuid = MM_SP_UUID;
+
+static u16 mm_sp_id;
+
+#endif
+
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -24,6 +59,7 @@ struct mm_connection {
 	u32 session;
 };
 
+#if (IS_ENABLED(CONFIG_OPTEE))
 /**
  * get_connection() - Retrieve OP-TEE session for a specific UUID.
  *
@@ -143,13 +179,252 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 
 	return ret;
 }
+#endif
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+/**
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notifies the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret = -1;
+	struct udevice *dev;
+
+	uclass_first_device(UCLASS_FFA, &dev);
+	if (!dev) {
+		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
+		return -ENODEV;
+	}
+
+	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
+
+	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
+	if (ret != 0)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	if (sp_event_ret == MM_SUCCESS)
+		return 0;
+
+	/* Failure to notify the MM SP */
+
+	return -EACCES;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+	struct udevice *dev;
+
+	uclass_first_device(UCLASS_FFA, &dev);
+	if (!dev) {
+		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
+		return -ENODEV;
+	}
+
+	/* Get from the driver the count of the SPs matching the UUID */
+	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, NULL);
+	if (ret != 0) {
+		log_err("EFI: Failure in querying SPs count (%d), MM SP discovery failure\n", ret);
+		return ret;
+	}
+
+	if (!count) {
+		log_info("EFI: No MM partition found\n");
+		return ret;
+	}
+
+	/* Pre-allocate a buffer to be filled by the driver with ffa_partition_info structs */
+
+	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
+
+	parts_info = calloc(count, sizeof(*parts_info));
+	if (!parts_info)
+		return -ENOMEM;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, parts_info);
+	if (ret) {
+		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/* MM SPs found , use the first one */
+
+	mm_sp_id = parts_info[0].id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	free(parts_info);
+
+	return 0;
+}
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	efi_status_t efi_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
+		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+
+	switch (ffa_ret) {
+	case 0: {
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		efi_ret = EFI_SUCCESS;
+		break;
+	}
+	case -EINVAL:
+		efi_ret = EFI_DEVICE_ERROR;
+		break;
+	case -EPERM:
+		efi_ret = EFI_INVALID_PARAMETER;
+		break;
+	case -EACCES:
+		efi_ret = EFI_ACCESS_DENIED;
+		break;
+	case -EBUSY:
+		efi_ret = EFI_OUT_OF_RESOURCES;
+		break;
+	default:
+		efi_ret = EFI_ACCESS_DENIED;
+	}
+
+	unmap_sysmem(virt_shared_buf);
+	return efi_ret;
+}
+#endif
+
+/**
+ * select_ffa_mm_comms() - checks FF-A support availability
+ *
+ * Making sure FF-A is compiled in. If that's the case try to make sure
+ * the FF-A bus is probed successfully which means FF-A communication
+ * with secure world works and ready to be used.
+ *
+ * Return:
+ *
+ * 0: FF-A ready for use. Otherwise, failure
+ */
+static efi_status_t select_ffa_mm_comms(void)
+{
+	efi_status_t ret = EFI_UNSUPPORTED;
+
+	if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) {
+		struct udevice *dev;
+
+		uclass_first_device(UCLASS_FFA, &dev);
+		if (!dev) {
+			log_err("EFI: Cannot find FF-A bus device, cannot select FF-A comms\n");
+			ret = EFI_NOT_READY;
+		} else {
+			ret = EFI_SUCCESS;
+		}
+	}
+
+	return ret;
+}
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
@@ -162,7 +437,17 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+	ret = select_ffa_mm_comms();
+	if (ret != EFI_SUCCESS) {
+#if (IS_ENABLED(CONFIG_OPTEE))
+		ret = optee_mm_communicate(comm_buf, dsize);
+#endif
+	} else {
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+		ret = ffa_mm_communicate(comm_buf, dsize);
+#endif
+	}
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -258,6 +543,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
 		goto out;
 	}
 	*size = var_payload->size;
+
+	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
+			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
+				MM_VARIABLE_COMMUNICATE_SIZE;
+	#endif
+
 	/*
 	 * There seems to be a bug in EDK2 miscalculating the boundaries and
 	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
@@ -697,7 +989,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v10 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2023-03-28 16:11                                                                                       ` [PATCH v10 " Abdellatif El Khlifi
                                                                                                           ` (8 preceding siblings ...)
  2023-03-28 16:11                                                                                         ` [PATCH v10 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-03-28 16:11                                                                                         ` Abdellatif El Khlifi
  2023-04-02  2:41                                                                                           ` Simon Glass
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-28 16:11 UTC (permalink / raw)
  To: sjg
  Cc: Drew.Reed, abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, robh, sudeep.holla, trini, u-boot,
	xueliang.zhong

turn on EFI MM communication

On corstone1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

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>

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

v9: update copyright string

v8:

* drop OP-TEE configs from Corstone-1000 defconfig

v7:

* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
  FFA_SHARED_MM_BUFFER_OFFSET
* update FFA_SHARED_MM_BUFFER_ADDR value

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

 configs/corstone1000_defconfig |  2 ++
 include/configs/corstone1000.h | 15 +++++++++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index 74250c7524..a7bfcbb2b9 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -52,3 +52,5 @@ CONFIG_DM_SERIAL=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760=y
 CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
index 3347c11792..4ef1f05e40 100644
--- a/include/configs/corstone1000.h
+++ b/include/configs/corstone1000.h
@@ -1,9 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * (C) Copyright 2022 ARM Limited
  * (C) Copyright 2022 Linaro
  * Rui Miguel Silva <rui.silva@linaro.org>
- * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  *
  * Configuration for Corstone1000. Parts were derived from other ARM
  * configurations.
@@ -14,6 +16,15 @@
 
 #include <linux/sizes.h>
 
+#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
+
+/*
+ * shared buffer physical address used for communication between
+ * u-boot and the MM SP
+ */
+#define FFA_SHARED_MM_BUFFER_ADDR	0x02000000UL
+#define FFA_SHARED_MM_BUFFER_OFFSET	0
+
 #define V2M_BASE		0x80000000
 
 #define CFG_PL011_CLOCK	50000000
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-03-28 16:11                                                                                         ` [PATCH v10 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-03-29 20:02                                                                                           ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-03-29 20:02 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sudeep.holla, trini, u-boot, xueliang.zhong

On Wed, 29 Mar 2023 at 05:12, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> add support for x0-x17 registers used by the SMC calls
>
> In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
> Results are returned in x0-x17.
>
> This work is inspired from the following kernel commit:
>
> arm64: smccc: Add support for SMCCCv1.2 extended input/output registers
>
> [1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
>
> ---
> Changelog:
> ===============
>
> v9:
>
> * update the copyright string
>
> v7:
>
> * improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS
>
> v4:
>
> * rename the commit title and improve description
>   new commit title: the current
>
> v3:
>
> * port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
>   commit title:
>       arm64: smccc: add Xn registers support used by SMC calls
>
>  arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
>  arch/arm/lib/asm-offsets.c      | 16 +++++++++
>  include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
>  3 files changed, 117 insertions(+), 1 deletion(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-03-28 16:11                                                                                         ` [PATCH v10 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-03-29 20:02                                                                                           ` Simon Glass
  2023-03-30 10:27                                                                                             ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-03-29 20:02 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sudeep.holla, trini, u-boot, xueliang.zhong

On Wed, 29 Mar 2023 at 05:12, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> provide a test case
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Cc: Simon Glass <sjg@chromium.org>
> ---
>  MAINTAINERS       |  5 +++++
>  test/lib/Makefile |  1 +
>  test/lib/uuid.c   | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 50 insertions(+)
>  create mode 100644 test/lib/uuid.c

Still this is missing a change log. Please can you check your process.
Do you use patman?

Can you use ut_asserteq_mem()? If not, please add a comment as to why
that doesn't work, so it is clear.

Regards,
SImon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-03-29 20:02                                                                                           ` Simon Glass
@ 2023-03-30 10:27                                                                                             ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-03-30 10:27 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, nd

On Thu, Mar 30, 2023 at 09:02:18AM +1300, Simon Glass wrote:
> On Wed, 29 Mar 2023 at 05:12, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > provide a test case
> >
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Cc: Simon Glass <sjg@chromium.org>
> > ---
> >  MAINTAINERS       |  5 +++++
> >  test/lib/Makefile |  1 +
> >  test/lib/uuid.c   | 44 ++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 50 insertions(+)
> >  create mode 100644 test/lib/uuid.c
> 
> Still this is missing a change log. Please can you check your process.

This commit has been introduced in v9 patchset. No change made in the v10.
In v11 I'll add a changelog reflecting the use of ut_asserteq_mem().

> Do you use patman?

No, I'm planning to learn about it.

> 
> Can you use ut_asserteq_mem()? If not, please add a comment as to why
> that doesn't work, so it is clear.

Thanks. It works and will be included in v11.
Could you please provide a feedback for the other commits so I can address
everything in one go in patchset v11 ?

Cheers
Abdellatif

> 
> Regards,
> SImon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-03-28 16:11                                                                                         ` [PATCH v10 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-03-31  8:29                                                                                           ` Ilias Apalodimas
  2023-04-12  9:59                                                                                             ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-03-31  8:29 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: sjg, Drew.Reed, achin.gupta, jens.wiklander, nd, robh,
	sudeep.holla, trini, u-boot, xueliang.zhong,
	Gowtham Suresh Kumar

Hi Abdellatif,

On Tue, Mar 28, 2023 at 05:11:56PM +0100, Abdellatif El Khlifi wrote:
> Add MM communication support using FF-A transport
>
> This feature allows accessing MM partitions services through
> EFI MM communication protocol. MM partitions such as StandAlonneMM
> or smm-gateway secure partitions which reside in secure world.
>
> An MM shared buffer and a door bell event are used to exchange
> the data.
>
> The data is used by EFI services such as GetVariable()/SetVariable()
> and copied from the communication buffer to the MM shared buffer.
>
> The secure partition is notified about availability of data in the
> MM shared buffer by an FF-A message (door bell).
>
> On such event, MM SP can read the data and updates the MM shared
> buffer with the response data.
>
> The response data is copied back to the communication buffer and
> consumed by the EFI subsystem.
>
> MM communication protocol supports FF-A 64-bit direct messaging.
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>
>
> ---
> Changelog:
> ===============
>
> v10:
>
> * use the FF-A driver Uclass operations
> * use uclass_first_device()
> * addressing nits
>
> v9: align how FF-A is used with FF-A discovery through DM
>
> v8:
>
> * isolate the compilation choices between FF-A and OP-TEE
> * update partition_info_get() second argument to be an SP count
> * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7:
>
> * set the MM door bell event to use 64-bit direct messaging
> * issue a compile time error when one of these macros are not found :
>   FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
> * make mm_sp_svc_uuid static
> * replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
> * improve use of unmap_sysmem() in ffa_mm_communicate()
>
> v6:
>
> * add FF-A runtime discovery at MM communication level
> * drop EFI runtime support for FF-A MM communication
> * revert the changes in include/mm_communication.h for
>   efi_mm_communicate_header and smm_variable_access structures
>
> v4:
>
> * use the new FF-A driver interfaces
> * discover MM partitions at runtime
> * copy FF-A driver private data to EFI runtime section at
>   ExitBootServices()
> * drop use of FFA_ERR_STAT_SUCCESS error code
> * replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
>   in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
> * revert the error log in mm_communicate() in case of failure
> * remove packed attribute from efi_mm_communicate_header and
>   smm_variable_communicate_header
>
> v2:
>
> * set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings
>
> v1:
>
> * introduce FF-A MM communication
>
>  include/mm_communication.h        |   6 +
>  lib/efi_loader/Kconfig            |  14 +-
>  lib/efi_loader/efi_variable_tee.c | 300 +++++++++++++++++++++++++++++-
>  3 files changed, 314 insertions(+), 6 deletions(-)
>
> diff --git a/include/mm_communication.h b/include/mm_communication.h
> index e65fbde60d..87509fec3f 100644
> --- a/include/mm_communication.h
> +++ b/include/mm_communication.h
> @@ -6,6 +6,9 @@
>   *  Copyright (c) 2017, Intel Corporation. All rights reserved.
>   *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
>   *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
> + *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *    Authors:
> + *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>
>  #ifndef _MM_COMMUNICATION_H_
> @@ -13,6 +16,9 @@
>
>  #include <part_efi.h>
>
> +/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
> +#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
> +
>  /*
>   * Interface to the pseudo Trusted Application (TA), which provides a
>   * communication channel with the Standalone MM (Management Mode)
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index c5835e6ef6..08a6b84101 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
>  	  stored as file /ubootefi.var on the EFI system partition.
>
>  config EFI_MM_COMM_TEE
> -	bool "UEFI variables storage service via OP-TEE"
> -	depends on OPTEE
> +	bool "UEFI variables storage service via the trusted world"
> +	depends on OPTEE || ARM_FFA_TRANSPORT
>  	help
> +	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
> +	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> +	  When using the u-boot FF-A  driver any MM SP is supported.
> +
>  	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
>  	  variable related operations to that. The application will verify,
>  	  authenticate and store the variables on an RPMB.
>
> +	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> +	  operations to the MM SP running in the secure world.
> +	  A door bell mechanism is used to notify the SP when there is data in the shared
> +	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
> +	  the door bell event.
> +
>  config EFI_VARIABLE_NO_STORE
>  	bool "Don't persist non-volatile UEFI variables"
>  	help
> diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> index dfef18435d..a3060b4e7e 100644
> --- a/lib/efi_loader/efi_variable_tee.c
> +++ b/lib/efi_loader/efi_variable_tee.c
> @@ -4,9 +4,14 @@
>   *
>   *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
>   *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
> + *  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 <efi.h>
>  #include <efi_api.h>
>  #include <efi_loader.h>
> @@ -15,6 +20,36 @@
>  #include <malloc.h>
>  #include <mm_communication.h>
>
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +
> +#include <arm_ffa.h>
> +#include <cpu_func.h>
> +#include <mapmem.h>
> +
> +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_SIZE 0
> +#endif
> +
> +#ifndef FFA_SHARED_MM_BUFFER_OFFSET
> +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_OFFSET 0
> +#endif
> +
> +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_ADDR 0
> +#endif
> +
> +/* MM return codes */
> +#define MM_SUCCESS (0)
> +
> +static const char *mm_sp_svc_uuid = MM_SP_UUID;
> +
> +static u16 mm_sp_id;
> +
> +#endif
> +
>  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
>  static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
>  static efi_uintn_t max_payload_size;	/* func + data */
> @@ -24,6 +59,7 @@ struct mm_connection {
>  	u32 session;
>  };
>
> +#if (IS_ENABLED(CONFIG_OPTEE))
>  /**
>   * get_connection() - Retrieve OP-TEE session for a specific UUID.
>   *
> @@ -143,13 +179,252 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
>
>  	return ret;
>  }
> +#endif
> +
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +
> +/**
> + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> + *
> + * Notifies the MM partition in the trusted world that
> + * data is available in the shared buffer.
> + * This is a blocking call during which trusted world has exclusive access
> + * to the MM shared buffer.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_notify_mm_sp(void)
> +{
> +	struct ffa_send_direct_data msg = {0};
> +	int ret;
> +	int sp_event_ret = -1;
> +	struct udevice *dev;
> +
> +	uclass_first_device(UCLASS_FFA, &dev);
> +	if (!dev) {
> +		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
> +		return -ENODEV;
> +	}
> +
> +	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
> +
> +	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
> +	if (ret != 0)

We usually do if (!ret)

> +		return ret;
> +
> +	sp_event_ret = msg.data0; /* x3 */
> +
> +	if (sp_event_ret == MM_SUCCESS)
> +		return 0;
> +
> +	/* Failure to notify the MM SP */
> +
> +	return -EACCES;
> +}
> +
> +/**
> + * ffa_discover_mm_sp_id() - Query the MM partition ID
> + *
> + * Use the FF-A driver to get the MM partition ID.
> + * If multiple partitions are found, use the first one.
> + * This is a boot time function.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_discover_mm_sp_id(void)
> +{
> +	u32 count = 0;
> +	int ret;
> +	struct ffa_partition_info *parts_info;
> +	struct udevice *dev;
> +
> +	uclass_first_device(UCLASS_FFA, &dev);
> +	if (!dev) {
> +		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
> +		return -ENODEV;
> +	}
> +
> +	/* Get from the driver the count of the SPs matching the UUID */
> +	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, NULL);
> +	if (ret != 0) {
> +		log_err("EFI: Failure in querying SPs count (%d), MM SP discovery failure\n", ret);
> +		return ret;
> +	}
> +
> +	if (!count) {
> +		log_info("EFI: No MM partition found\n");
> +		return ret;
> +	}
> +
> +	/* Pre-allocate a buffer to be filled by the driver with ffa_partition_info structs */
> +
> +	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
> +
> +	parts_info = calloc(count, sizeof(*parts_info));
> +	if (!parts_info)
> +		return -ENOMEM;
> +
> +	/* Ask the driver to fill the buffer with the SPs info */
> +	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, parts_info);
> +	if (ret) {
> +		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
> +		free(parts_info);
> +		return ret;
> +	}
> +
> +	/* MM SPs found , use the first one */
> +
> +	mm_sp_id = parts_info[0].id;
> +
> +	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
> +
> +	free(parts_info);
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
> + * @comm_buf:		locally allocated communication buffer used for rx/tx
> + * @dsize:				communication buffer size
> + *
> + * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
> + * that there is data to read from the shared buffer.
> + * Communication with the MM SP is performed using FF-A transport.
> + * On the event, MM SP can read the data from the buffer and
> + * update the MM shared buffer with response data.
> + * The response data is copied back to the communication buffer.
> + *
> + * Return:
> + *
> + * EFI status code
> + */
> +static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
> +{
> +	ulong tx_data_size;
> +	int ffa_ret;
> +	efi_status_t efi_ret;
> +	struct efi_mm_communicate_header *mm_hdr;
> +	void *virt_shared_buf;
> +
> +	if (!comm_buf)
> +		return EFI_INVALID_PARAMETER;
> +
> +	/* Discover MM partition ID at boot time */
> +	if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
> +		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
> +		return EFI_UNSUPPORTED;
> +	}
> +
> +	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> +	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
> +
> +	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
> +		return EFI_INVALID_PARAMETER;
> +
> +	/* Copy the data to the shared buffer */
> +
> +	virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
> +	memcpy(virt_shared_buf, comm_buf, tx_data_size);
> +
> +	/*
> +	 * The secure world might have cache disabled for
> +	 * the device region used for shared buffer (which is the case for Optee).
> +	 * In this case, the secure world reads the data from DRAM.
> +	 * Let's flush the cache so the DRAM is updated with the latest data.
> +	 */
> +#ifdef CONFIG_ARM64
> +	invalidate_dcache_all();
> +#endif
> +
> +	/* Announce there is data in the shared buffer */
> +
> +	ffa_ret = ffa_notify_mm_sp();
> +
> +	switch (ffa_ret) {
> +	case 0: {
> +		ulong rx_data_size;
> +		/* Copy the MM SP response from the shared buffer to the communication buffer */
> +		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> +			sizeof(efi_guid_t) +
> +			sizeof(size_t);
> +
> +		if (rx_data_size > comm_buf_size) {
> +			efi_ret = EFI_OUT_OF_RESOURCES;
> +			break;
> +		}
> +
> +		memcpy(comm_buf, virt_shared_buf, rx_data_size);
> +		efi_ret = EFI_SUCCESS;
> +		break;
> +	}
> +	case -EINVAL:
> +		efi_ret = EFI_DEVICE_ERROR;
> +		break;
> +	case -EPERM:
> +		efi_ret = EFI_INVALID_PARAMETER;
> +		break;
> +	case -EACCES:
> +		efi_ret = EFI_ACCESS_DENIED;
> +		break;
> +	case -EBUSY:
> +		efi_ret = EFI_OUT_OF_RESOURCES;
> +		break;
> +	default:
> +		efi_ret = EFI_ACCESS_DENIED;
> +	}
> +
> +	unmap_sysmem(virt_shared_buf);
> +	return efi_ret;
> +}
> +#endif
> +
> +/**
> + * select_ffa_mm_comms() - checks FF-A support availability
> + *
> + * Making sure FF-A is compiled in. If that's the case try to make sure
> + * the FF-A bus is probed successfully which means FF-A communication
> + * with secure world works and ready to be used.
> + *
> + * Return:
> + *
> + * 0: FF-A ready for use. Otherwise, failure
> + */
> +static efi_status_t select_ffa_mm_comms(void)
> +{
> +	efi_status_t ret = EFI_UNSUPPORTED;
> +
> +	if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) {
> +		struct udevice *dev;
> +
> +		uclass_first_device(UCLASS_FFA, &dev);
> +		if (!dev) {
> +			log_err("EFI: Cannot find FF-A bus device, cannot select FF-A comms\n");
> +			ret = EFI_NOT_READY;
> +		} else {
> +			ret = EFI_SUCCESS;
> +		}
> +	}
> +
> +	return ret;
> +}
>
>  /**
> - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
> + * mm_communicate() - Adjust the communication buffer to the MM SP and send
>   * it to OP-TEE
>   *
> - * @comm_buf:		locally allocted communcation buffer
> + * @comm_buf:		locally allocated communication buffer
>   * @dsize:		buffer size
> + *
> + * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
> + * The comm_buf format is the same for both partitions.
> + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> + * When using the u-boot FF-A  driver, any MM SP is supported.
> + *
>   * Return:		status code
>   */
>  static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> @@ -162,7 +437,17 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
>  	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
>
> -	ret = optee_mm_communicate(comm_buf, dsize);
> +	ret = select_ffa_mm_comms();
> +	if (ret != EFI_SUCCESS) {
> +#if (IS_ENABLED(CONFIG_OPTEE))
> +		ret = optee_mm_communicate(comm_buf, dsize);
> +#endif
> +	} else {
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +		ret = ffa_mm_communicate(comm_buf, dsize);
> +#endif

This is a bit confusing to read.  Why does select_ffa_mm_comms() have to
return and EFI return code?  It has nothing to do with EFI to begin with.

I think you can make select_ffa_mm_comms() return an enum with
OPTEE/FFA. The you can rewrite this a bit cleaner
Something along the lines of

efi_status_t ret = EFI_INVALID_PARAMETER;
enum transport_select;

transport_select = select_ffa_mm_comms();
if (transport_select == OPTEE)
    ret = optee_mm_communicate(comm_buf, dsize);
else
    ret = ffa_mm_communicate(comm_buf, dsize);

While at it stub the ffa_mm_communicate() and optee_mm_communicate()
functions so they are always defined but return EFI_UNSUPPORTED if the
Kconfig is not selected while printing an appropriate error at the same
time to inform the user which Kconfig option is missing.

> +	}
> +
>  	if (ret != EFI_SUCCESS) {
>  		log_err("%s failed!\n", __func__);
>  		return ret;
> @@ -258,6 +543,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
>  		goto out;
>  	}
>  	*size = var_payload->size;
> +
> +	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
> +			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
> +				MM_VARIABLE_COMMUNICATE_SIZE;
> +	#endif
> +
>  	/*
>  	 * There seems to be a bug in EDK2 miscalculating the boundaries and
>  	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> @@ -697,7 +989,7 @@ void efi_variables_boot_exit_notify(void)
>  		ret = EFI_NOT_FOUND;
>
>  	if (ret != EFI_SUCCESS)
> -		log_err("Unable to notify StMM for ExitBootServices\n");
> +		log_err("Unable to notify the MM partition for ExitBootServices\n");
>  	free(comm_buf);
>
>  	/*
> --
> 2.25.1
>

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 05/10] arm_ffa: introduce armffa command
  2023-03-28 16:11                                                                                         ` [PATCH v10 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-04-02  2:40                                                                                           ` Simon Glass
  2023-04-12  9:48                                                                                             ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-04-02  2:40 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, Ilias Apalodimas, Jens Wiklander, nd,
	Rob Herring, Sudeep Holla, Tom Rini, U-Boot Mailing List,
	Xueliang Zhong, Heinrich Schuchardt

Hi Abdellatif,

On Wed, 29 Mar 2023 at 05:12, Abdellatif El Khlifi <
abdellatif.elkhlifi@arm.com> wrote:
>
> Provide armffa command showcasing the use of the U-Boot FF-A support
>
> armffa is a command showcasing how to invoke FF-A operations.
> This provides a guidance to the client developers on how to
> call the FF-A bus interfaces. The command also allows to gather secure
> partitions information and ping these  partitions. The command is also
> helpful in testing the communication with secure partitions.
>
> For more details please refer to the command documentation [1].
>
> [1]: doc/usage/cmd/armffa.rst
>
> 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>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
>
> ---
> Changelog:
> ===============
>
> v10:
>
> * use the FF-A driver Uclass operations
> * use uclass_first_device()
> * address nits
>
> v9:
>
> * remove manual FF-A discovery and use DM
> * use DM class APIs to probe and interact with the FF-A bus
> * add doc/usage/cmd/armffa.rst
>
> v8:
>
> * update partition_info_get() second argument to be an SP count
> * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7:
>
> * adapt do_ffa_dev_list() following the recent update on
>   uclass_first_device/uclass_next_device functions (they return void now)
> * set armffa command to use 64-bit direct messaging
>
> v4:
>
> * remove pattern data in do_ffa_msg_send_direct_req
>
> v3:
>
> * use the new driver interfaces (partition_info_get, sync_send_receive)
>   in armffa command
>
> v2:
>
> * replace use of ffa_helper_init_device function by
>  ffa_helper_bus_discover
>
> v1:
>
> * introduce armffa command
>
>  MAINTAINERS                      |   2 +
>  cmd/Kconfig                      |  10 ++
>  cmd/Makefile                     |   2 +
>  cmd/armffa.c                     | 238 +++++++++++++++++++++++++++++++
>  doc/arch/arm64.ffa.rst           |   7 +
>  doc/usage/cmd/armffa.rst         | 107 ++++++++++++++
>  doc/usage/index.rst              |   1 +
>  drivers/firmware/arm-ffa/Kconfig |   1 +
>  8 files changed, 368 insertions(+)
>  create mode 100644 cmd/armffa.c
>  create mode 100644 doc/usage/cmd/armffa.rst
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 62c30184bb..add208e4ef 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -269,7 +269,9 @@ F:  configs/cortina_presidio-asic-pnand_defconfig
>  ARM FF-A
>  M:     Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>  S:     Maintained
> +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
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index ba5ec69293..b814a20d8a 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -934,6 +934,16 @@ endmenu
>
>  menu "Device access commands"
>
> +config CMD_ARMFFA
> +       bool "Arm FF-A test command"
> +       depends on ARM_FFA_TRANSPORT
> +       help
> +         Provides a test command for the FF-A support
> +         supported options:
> +               - Listing the partition(s) info
> +               - Sending a data pattern to the specified partition
> +               - Displaying the arm_ffa device info
> +
>  config CMD_ARMFLASH
>         #depends on FLASH_CFI_DRIVER
>         bool "armflash"
> diff --git a/cmd/Makefile b/cmd/Makefile
> index d95833b2de..a1eb45f881 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -12,6 +12,8 @@ obj-y += panic.o
>  obj-y += version.o
>
>  # command
> +
> +obj-$(CONFIG_CMD_ARMFFA) += armffa.o
>  obj-$(CONFIG_CMD_ACPI) += acpi.o
>  obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
>  obj-$(CONFIG_CMD_AES) += aes.o
> diff --git a/cmd/armffa.c b/cmd/armffa.c
> new file mode 100644
> index 0000000000..d983a23bbc
> --- /dev/null
> +++ b/cmd/armffa.c
> @@ -0,0 +1,238 @@
> +// 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 <command.h>
> +#include <dm.h>
> +#include <mapmem.h>
> +#include <stdlib.h>
> +#include <asm/io.h>
> +
> +/**
> + * do_ffa_getpart() - implementation of the getpart subcommand
> + * @cmdtp:             Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * This function queries the secure partition information which the UUID
is provided

s/This function queries/Query/

We know it is a function so try to be brief and use the imperative mood
like you do in commit messages.

> + * as an argument. The function uses the arm_ffa driver
partition_info_get operation
> + * which implements FFA_PARTITION_INFO_GET ABI to retrieve the data.
> + * The input UUID string is expected to be in big endian format.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
> +{
> +       u32 count = 0;
> +       int ret;
> +       struct ffa_partition_info *parts_info;
> +       u32 info_idx;
> +       struct udevice *dev = NULL;
> +
> +       if (argc != 1)
> +               return -EINVAL;

Since this is a command handler, you must return CMD_RET_USAGE here. Please
fix globally.


> +
> +       uclass_first_device(UCLASS_FFA, &dev);
> +       if (!dev) {

ret = uclass_first_device_err(...)
if (ret) {

(please fix globally)

> +               log_err("[FFA][CMD] Cannot find FF-A bus device\n");
> +               return -ENODEV;

CMD_RET_FAILURE - please fix throughout. Often it is easier to put all this
code (after arg checking) in a separate function which returns an error
code, then have the do_... function check that and either return 0 or print
a message and return CMD_RET_FAILURE.

> +       }
> +
> +       /* Mode 1: getting the number of secure partitions */
> +       ret = ffa_partition_info_get(dev, argv[0], &count, NULL);
> +       if (ret) {
> +               log_err("[FFA][CMD] Failure in querying partitions count
(error code: %d)\n", ret);

%dE gives you a nice error name if you want it.

Do you think you need the [FFA][CMD] stuff? Just the message should be
enough.

> +               return ret;
> +       }
> +
> +       if (!count) {
> +               log_info("[FFA][CMD] No secure partition found\n");
> +               return ret;
> +       }
> +
> +       /*
> +        * Pre-allocate a buffer to be filled by the driver
> +        * with ffa_partition_info structs
> +        */
> +
> +       log_info("[FFA][CMD] Pre-allocating %d partition(s) info
structures\n", count);
> +
> +       parts_info = calloc(count, sizeof(struct ffa_partition_info));

Just use a local variable and avoid the allocation.

> +       if (!parts_info)
> +               return -EINVAL;
> +
> +       /* Ask the driver to fill the buffer with the SPs info */
> +
> +       ret = ffa_partition_info_get(dev, argv[0], &count, parts_info);
> +       if (ret) {
> +               log_err("[FFA][CMD] Failure in querying partition(s) info
(error code: %d)\n", ret);
> +               free(parts_info);
> +               return ret;
> +       }
> +
> +       /* SPs found , show the partition information */
> +       for (info_idx = 0; info_idx < count ; info_idx++) {

We generally use 'i' for loops as it is shorter.

> +               log_info("[FFA][CMD] Partition: id = 0x%x , exec_ctxt
0x%x , properties 0x%x\n",

You don't need the 0x. Generally hex is used for everything in U-Boot. If
you feel there is ambiguity, use %#x

> +                        parts_info[info_idx].id,
> +                        parts_info[info_idx].exec_ctxt,
> +                        parts_info[info_idx].properties);
> +       }
> +
> +       free(parts_info);
> +
> +       return 0;
> +}
> +
> +/**
> + * do_ffa_ping() - implementation of the ping subcommand
> + * @cmdtp:             Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * This function sends data to the secure partition which the ID is
provided

partition for which ?

> + * as an argument. The function uses the arm_ffa driver
sync_send_receive operation
> + * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive
data.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const
argv[])
> +{
> +       struct ffa_send_direct_data msg = {
> +                       .data0 = 0xaaaaaaaa,
> +                       .data1 = 0xbbbbbbbb,
> +                       .data2 = 0xcccccccc,
> +                       .data3 = 0xdddddddd,
> +                       .data4 = 0xeeeeeeee,
> +       };
> +       u16 part_id;
> +       int ret;
> +       struct udevice *dev = NULL;
> +
> +       if (argc != 1)
> +               return -EINVAL;
> +
> +       errno = 0;
> +       part_id = strtoul(argv[0], NULL, 16);
> +
> +       if (errno) {
> +               log_err("[FFA][CMD] Invalid partition ID\n");
> +               return -EINVAL;
> +       }
> +
> +       uclass_first_device(UCLASS_FFA, &dev);
> +       if (!dev) {
> +               log_err("[FFA][CMD] Cannot find FF-A bus device\n");
> +               return -ENODEV;
> +       }
> +
> +       ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
> +       if (!ret) {
> +               u8 cnt;
> +
> +               log_info("[FFA][CMD] SP response:\n[LSB]\n");
> +               for (cnt = 0;
> +                    cnt < sizeof(struct ffa_send_direct_data) /
sizeof(u64);
> +                    cnt++)
> +                       log_info("[FFA][CMD] 0x%llx\n", ((u64
*)&msg)[cnt]);
> +       } else {
> +               log_err("[FFA][CMD] Sending direct request error (%d)\n",
ret);
> +       }
> +
> +       return ret;
> +}
> +
> +/**
> + *do_ffa_devlist() - implementation of the devlist subcommand
> + * @cmdtp: [in]                Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * This function queries the device belonging to the UCLASS_FFA
> + * class.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char
*const argv[])
> +{
> +       struct udevice *dev = NULL;
> +
> +       uclass_first_device(UCLASS_FFA, &dev);
> +       if (!dev) {
> +               log_err("[FFA][CMD] Cannot find FF-A bus device\n");
> +               return -ENODEV;
> +       }
> +
> +       log_info("[FFA][CMD] device name %s, dev %08x, driver name %s,
ops %08x\n",
> +                dev->name,
> +                (u32)map_to_sysmem(dev),

use %p as this is a pointer

> +                dev->driver->name,
> +                (u32)map_to_sysmem(dev->driver->ops));

Use %p as this is a pointer

> +
> +       return 0;
> +}
> +
> +static struct cmd_tbl armffa_commands[] = {
> +       U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_getpart, "", ""),
> +       U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_ping, "", ""),
> +       U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_devlist, "", ""),
> +};
> +
> +/**
> + * do_armffa() - the armffa command main function
> + * @cmdtp:     Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * This function identifies which armffa subcommand to run.
> + * Then, it makes sure the arm_ffa device is probed and
> + * ready for use.
> + * Then, it runs the subcommand.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char
*const argv[])

You can use U_BOOT_CMD_WITH_SUBCMDS and drop this function

> +{
> +       struct cmd_tbl *armffa_cmd;
> +       int ret;
> +
> +       if (argc < 2)
> +               return CMD_RET_USAGE;
> +
> +       armffa_cmd = find_cmd_tbl(argv[1], armffa_commands,
ARRAY_SIZE(armffa_commands));
> +
> +       argc -= 2;
> +       argv += 2;
> +
> +       if (!armffa_cmd || argc > armffa_cmd->maxargs)
> +               return CMD_RET_USAGE;
> +
> +       ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
> +
> +       return cmd_process_error(armffa_cmd, ret);
> +}
> +
> +U_BOOT_CMD(armffa, 4, 1, do_armffa,
> +          "Arm FF-A operations test command",
> +          "getpart <partition UUID>\n"
> +          "     - lists the partition(s) info\n"
> +          "ping <partition ID>\n"
> +          "     - sends a data pattern to the specified partition\n"
> +          "devlist\n"
> +          "     - displays information about the FF-A device/driver\n");
> diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> index ddf6435402..5fedb0c255 100644
> --- a/doc/arch/arm64.ffa.rst
> +++ b/doc/arch/arm64.ffa.rst
> @@ -218,6 +218,13 @@ The following features are provided:
>
>  - FF-A bus can be compiled and used without EFI
>
> +The armffa command
> +-----------------------------------
> +
> +armffa is an implementation defined command showcasing how to use the
FF-A bus and how to invoke the driver operations.
> +
> +Please refer the command documentation at doc/usage/cmd/armffa.rst
> +
>  Example of boot logs with FF-A enabled
>  --------------------------------------
>
> diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
> new file mode 100644
> index 0000000000..9bf59e393b
> --- /dev/null
> +++ b/doc/usage/cmd/armffa.rst
> @@ -0,0 +1,107 @@
> +.. SPDX-License-Identifier: GPL-2.0+:
> +
> +armffa command
> +==============
> +
> +Synopsis
> +--------
> +
> +::
> +
> +   armffa [sub-command] [arguments]
> +
> +   sub-commands:
> +
> +        getpart [partition UUID]
> +
> +            lists the partition(s) info
> +
> +        ping [partition ID]
> +
> +            sends a data pattern to the specified partition
> +
> +        devlist
> +
> +            displays information about the FF-A device/driver
> +
> +Description
> +-----------
> +
> +armffa is a command showcasing how to use the FF-A bus and how to invoke
its operations.
> +
> +This provides a guidance to the client developers on how to call the
FF-A bus interfaces.
> +
> +The command also allows to gather secure partitions information and ping
these  partitions.
> +
> +The command is also helpful in testing the communication with secure
partitions.
> +
> +Example
> +-------
> +
> +The following examples are run on Corstone-1000 platform with debug logs
enabled.
> +
> +* ping
> +
> +::
> +
> +   corstone1000# armffa ping 0x8003
> +   [FFA][CMD] SP response:
> +   [LSB]
> +   [FFA][CMD] 0xfffffffe
> +   [FFA][CMD] 0x0
> +   [FFA][CMD] 0x0
> +   [FFA][CMD] 0x0
> +   [FFA][CMD] 0x0
> +
> +* ping (failure case)
> +
> +::
> +
> +   corstone1000# armffa ping 0x8009
> +   [FFA][CMD] Sending direct request error (-22)
> +   Command 'ping' failed: Error -22
> +
> +* getpart
> +
> +::
> +
> +   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
> +   [FFA] Preparing for checking partitions count
> +   [FFA] Searching partitions using the provided UUID
> +   [FFA] No partition found. Querying framework ...
> +   [FFA] Reading partitions data from the RX buffer
> +   [FFA] Number of partition(s) matching the UUID: 1
> +   [FFA][CMD] Pre-allocating 1 partition(s) info structures
> +   [FFA] Preparing for filling partitions info
> +   [FFA] Searching partitions using the provided UUID
> +   [FFA] Partition ID 8003 matches the provided UUID
> +   [FFA][CMD] Partition: id = 0x8003 , exec_ctxt 0x1 , properties 0x3

To me this [FFA] stuff is redundant and it looks awful. Please drop it.

> +
> +* getpart (failure case)
> +
> +::
> +
> +   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7228
> +   [FFA] Preparing for checking partitions count
> +   [FFA] Searching partitions using the provided UUID
> +   [FFA] No partition found. Querying framework ...
> +   [FFA] INVALID_PARAMETERS: Unrecognized UUID
> +   [FFA][CMD] Failure in querying partitions count (error code: -22)
> +   Command 'getpart' failed: Error -22
> +
> +* devlist
> +
> +::
> +
> +   corstone1000# armffa devlist
> +   [FFA][CMD] device name arm_ffa, dev fdf41c30, driver name arm_ffa,
ops fffc0fc8
> +
> +Configuration
> +-------------
> +
> +The command is available if CONFIG_CMD_ARMFFA=y and
CONFIG_ARM_FFA_TRANSPORT=y.
> +
> +Return value
> +------------
> +
> +The return value $? is 0 (true) on success and a negative error code on
failure.
> diff --git a/doc/usage/index.rst b/doc/usage/index.rst
> index bc85e1d49a..df107fb710 100644
> --- a/doc/usage/index.rst
> +++ b/doc/usage/index.rst
> @@ -21,6 +21,7 @@ Shell commands
>
>     cmd/acpi
>     cmd/addrmap
> +   cmd/armffa
>     cmd/askenv
>     cmd/base
>     cmd/bdinfo
> diff --git a/drivers/firmware/arm-ffa/Kconfig
b/drivers/firmware/arm-ffa/Kconfig
> index 9200c8028b..a7d5392859 100644
> --- a/drivers/firmware/arm-ffa/Kconfig
> +++ b/drivers/firmware/arm-ffa/Kconfig
> @@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
>         depends on DM && ARM64
>         select ARM_SMCCC
>         select ARM_SMCCC_FEATURES
> +       imply CMD_ARMFFA
>         select LIB_UUID
>         select DEVRES
>         help
> --
> 2.25.1
>

Regards,
SImon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA
  2023-03-28 16:11                                                                                         ` [PATCH v10 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-04-02  2:40                                                                                           ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-04-02  2:40 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, Ilias Apalodimas, Jens Wiklander, nd,
	Rob Herring, Sudeep Holla, Tom Rini, U-Boot Mailing List,
	Xueliang Zhong, Heinrich Schuchardt

Hi Abdellatif,

On Wed, 29 Mar 2023 at 05:12, Abdellatif El Khlifi <
abdellatif.elkhlifi@arm.com> wrote:
>
> Add functional test cases for the FF-A support
>
> These tests rely on the FF-A sandbox emulator and FF-A
> sandbox driver which help in inspecting the FF-A communication.
>
> 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>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
>
> ---
> Changelog:
> ===============
>
> v10:
>
> * use the FF-A driver Uclass operations
> * use uclass_first_device()
> * replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT
> * address nits
>
> v9: align FF-A sandbox tests with FF-A discovery through DM
>
> v8:
>
>   * update partition_info_get() second argument to be an SP count
>   * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7: set the tests to use 64-bit direct messaging
>
> v4: align sandbox tests with the new FF-A driver interfaces
>  and new way of error handling
>
> v1: introduce sandbox tests
>
>  MAINTAINERS            |   1 +
>  doc/arch/arm64.ffa.rst |   1 +
>  test/dm/Makefile       |   2 +
>  test/dm/ffa.c          | 357 +++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 361 insertions(+)
>  create mode 100644 test/dm/ffa.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index b8019517ba..8f698b3f20 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -276,6 +276,7 @@ F:  doc/arch/arm64.ffa.rst
>  F:     doc/usage/cmd/armffa.rst
>  F:     drivers/firmware/arm-ffa/
>  F:     include/arm_ffa.h
> +F:     test/dm/ffa.c
>
>  ARM FREESCALE IMX
>  M:     Stefano Babic <sbabic@denx.de>
> diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> index 457a0e112e..5b1450f579 100644
> --- a/doc/arch/arm64.ffa.rst
> +++ b/doc/arch/arm64.ffa.rst
> @@ -38,6 +38,7 @@ The U-Boot FF-A support provides the following parts:
>    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.
> +- Sandbox FF-A test cases.
>
>  FF-A and SMC specifications
>  -------------------------------------------
> diff --git a/test/dm/Makefile b/test/dm/Makefile
> index 7a79b6e1a2..45563bdfb4 100644
> --- a/test/dm/Makefile
> +++ b/test/dm/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0+
>  #
>  # Copyright (c) 2013 Google, Inc
> +# Copyright 2022-2023 Arm Limited and/or its affiliates <
open-source-office@arm.com>
>
>  obj-$(CONFIG_UT_DM) += test-dm.o
>
> @@ -85,6 +86,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
>  obj-$(CONFIG_ACPI_PMC) += pmc.o
>  obj-$(CONFIG_DM_PMIC) += pmic.o
>  obj-$(CONFIG_DM_PWM) += pwm.o
> +obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o
>  obj-$(CONFIG_QFW) += qfw.o
>  obj-$(CONFIG_RAM) += ram.o
>  obj-y += regmap.o
> diff --git a/test/dm/ffa.c b/test/dm/ffa.c
> new file mode 100644
> index 0000000000..d493597521
> --- /dev/null
> +++ b/test/dm/ffa.c
> @@ -0,0 +1,357 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Functional tests for UCLASS_FFA  class
> + *
> + * 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 <console.h>
> +#include <dm.h>
> +#include <asm/sandbox_arm_ffa.h>
> +#include <asm/sandbox_arm_ffa_priv.h>
> +#include <dm/test.h>
> +#include <test/test.h>
> +#include <test/ut.h>
> +
> +/* Macros */
> +
> +#define LOG_MSG_SZ (100)
> +#define LOG_CMD_SZ (LOG_MSG_SZ * 2)
> +
> +/* Functional tests for the UCLASS_FFA */
> +
> +static int dm_test_ffa_log(struct unit_test_state *uts, char *msg)
> +{
> +       char cmd[LOG_CMD_SZ] = {0};
> +
> +       console_record_reset();
> +
> +       snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg);
> +       run_command(cmd, 0);
> +
> +       ut_assert_console_end();
> +
> +       return 0;
> +}
> +
> +static int check_fwk_version(struct ffa_priv *priv, struct
unit_test_state *uts)
> +{
> +       struct ffa_sandbox_data func_data;
> +       u32 fwk_version = 0;
> +
> +       func_data.data0 = &fwk_version;
> +       func_data.data0_size = sizeof(fwk_version);
> +       ut_assertok(sandbox_ffa_query_core_state(FFA_VERSION,
&func_data));
> +
> +       if (priv->dscvry_info.fwk_version != fwk_version) {
> +               char msg[LOG_MSG_SZ] = {0};
> +
> +               snprintf(msg, LOG_MSG_SZ,
> +                        "[%s]: Error: framework version: core = 0x%x ,
sandbox  = 0x%x", __func__,
> +                        priv->dscvry_info.fwk_version,
> +                        fwk_version);
> +
> +               dm_test_ffa_log(uts, msg);
> +               return CMD_RET_FAILURE;

This is not a command. You should use ut_assert(false) here, perhaps?
Please fix throughout.

> +       }
> +       return 0;
> +}
> +
> +static int check_endpoint_id(struct ffa_priv *priv, struct
unit_test_state *uts)
> +{
> +       if (priv->id) {
> +               char msg[LOG_MSG_SZ] = {0};
> +
> +               snprintf(msg, LOG_MSG_SZ,
> +                        "[%s]: Error: endpoint id: core = 0x%x",
__func__, priv->id);
> +               dm_test_ffa_log(uts, msg);
> +               return CMD_RET_FAILURE;
> +       }
> +       return 0;
> +}
> +
> +static int check_rxtxbuf(struct ffa_priv *priv, struct unit_test_state
*uts)
> +{
> +       if (!priv->pair.rxbuf || !priv->pair.txbuf) {
> +               char msg[LOG_MSG_SZ] = {0};
> +
> +               snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = %p txbuf
= %p", __func__,
> +                        priv->pair.rxbuf,
> +                        priv->pair.txbuf);
> +               dm_test_ffa_log(uts, msg);
> +               return CMD_RET_FAILURE;
> +       }
> +       return 0;
> +}
> +
> +static int check_features(struct ffa_priv *priv, struct unit_test_state
*uts)
> +{
> +       char msg[LOG_MSG_SZ] = {0};
> +
> +       if (priv->pair.rxtx_min_pages != RXTX_4K &&
> +           priv->pair.rxtx_min_pages != RXTX_16K &&
> +           priv->pair.rxtx_min_pages != RXTX_64K) {
> +               snprintf(msg,
> +                        LOG_MSG_SZ,
> +                        "[%s]: Error: FFA_RXTX_MAP features = 0x%lx",
> +                        __func__,
> +                        priv->pair.rxtx_min_pages);
> +               dm_test_ffa_log(uts, msg);
> +               return CMD_RET_FAILURE;

It's not clear to me why you are printing these messages? If should be
enough to use ut_assert() as it shows you where the error happened, in a
backtrace. Perhaps I am missing something?

> +       }
> +
> +       return 0;
> +}
> +
> +static int check_rxbuf_mapped_flag(u32 queried_func_id,
> +                                  u8 rxbuf_mapped,
> +                                  struct unit_test_state *uts)
> +{
> +       char msg[LOG_MSG_SZ] = {0};
> +
> +       switch (queried_func_id) {
> +       case FFA_RXTX_MAP:
> +               if (rxbuf_mapped)
> +                       return 0;
> +               break;
> +       case FFA_RXTX_UNMAP:
> +               if (!rxbuf_mapped)
> +                       return 0;
> +               break;
> +       default:
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue",
__func__,
> +                (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" :
"FFA_RXTX_UNMAP"));
> +       dm_test_ffa_log(uts, msg);
> +
> +       return CMD_RET_FAILURE;
> +}
> +
> +static int check_rxbuf_release_flag(u8 rxbuf_owned, struct
unit_test_state *uts)
> +{
> +       if (rxbuf_owned) {
> +               char msg[LOG_MSG_SZ];
> +
> +               snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not
released", __func__);
> +               dm_test_ffa_log(uts, msg);
> +               return CMD_RET_FAILURE;
> +       }
> +       return 0;
> +}
> +
> +static int  test_ffa_msg_send_direct_req(u16 part_id, struct
unit_test_state *uts)
> +{
> +       struct ffa_send_direct_data msg;
> +       u8 cnt;
> +       struct udevice *dev;
> +
> +       uclass_first_device(UCLASS_FFA, &dev);
> +       ut_assertnonnull(dev);
> +
> +       ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
> +
> +       for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) /
sizeof(u64); cnt++)
> +               ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]);
> +
> +       return 0;
> +}
> +
> +static int test_partitions_and_comms(const char *service_uuid,
> +                                    struct unit_test_state *uts)
> +{
> +       u32 count;
> +       struct ffa_partition_info *parts_info;
> +       u32 info_idx, exp_info_idx;
> +       int ret;
> +       struct udevice *dev;
> +       struct ffa_sandbox_data func_data;
> +       struct ffa_partitions *partitions;
> +
> +       uclass_first_device(UCLASS_FFA, &dev);
> +       ut_assertnonnull(dev);

ut_assertok(uclass_first_device_err(...

> +
> +       /* Get from the driver the count of the SPs matching the UUID */
> +       ret = ffa_partition_info_get(dev, service_uuid, &count, NULL);
> +       /* Make sure partitions are detected */
> +       ut_assertok(ret);
> +       ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
> +
> +       /* Pre-allocate a buffer to be filled by the driver with
ffa_partition_info structs */
> +
> +       parts_info = calloc(count, sizeof(struct ffa_partition_info));
> +       ut_assertnonnull(parts_info);

Use a local var

> +
> +       /* Ask the driver to fill the buffer with the SPs info */
> +       ret = ffa_partition_info_get(dev, service_uuid, &count,
parts_info);
> +       if (ret != 0) {
> +               free(parts_info);
> +               ut_assertok(ret);
> +       }
> +
> +       /* SPs found , verify the partitions information */
> +
> +       func_data.data0 = &partitions;
> +       func_data.data0_size = sizeof(struct ffa_partitions *);
> +       ut_assertok(sandbox_ffa_query_core_state(FFA_PARTITION_INFO_GET,
&func_data));
> +
> +       ret = CMD_RET_FAILURE;
> +
> +       for (info_idx = 0; info_idx < count ; info_idx++) {
> +               for (exp_info_idx = 0;
> +                    exp_info_idx < partitions->count;
> +                    exp_info_idx++) {
> +                       if (parts_info[info_idx].id ==
> +                          partitions->descs[exp_info_idx].info.id) {
> +                               ret = memcmp(&parts_info[info_idx],
> +
&partitions->descs[exp_info_idx]
> +                                            .info,
> +                                            sizeof(struct
ffa_partition_info));

ut_asserteq_mem(). Please take a look at the functions available.

> +                               if (ret)
> +                                       free(parts_info);
> +                               ut_assertok(ret);
> +                               /* Send and receive data from the current
partition */
> +
 test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
> +                       }
> +                       ret = 0;
> +               }
> +       }
> +
> +       free(parts_info);
> +
> +       /* Verify expected partitions found in the emulated secure world
*/
> +       ut_assertok(ret);
> +
> +       return 0;
> +}
> +
> +static int dm_test_ffa_ack(struct unit_test_state *uts)
> +{
> +       struct ffa_priv *priv;
> +       struct ffa_sandbox_data func_data;
> +       u8 rxbuf_flag = 0;
> +       const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
> +       const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
> +       int ret;
> +       struct udevice *dev;
> +
> +       /* Test probing the sandbox FF-A bus */
> +       uclass_first_device(UCLASS_FFA, &dev);
> +       ut_assertnonnull(dev);
> +
> +       /* Get a pointer to the sandbox FF-A bus private data */
> +       priv = dev_get_priv(dev);

I think you want dev_get_uclass_priv() here, based on my othe rcomment

> +
> +       /* Make sure the private data pointer is retrieved */
> +       ut_assertnonnull(priv);
> +
> +       /* Test FFA_VERSION */

[..]

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 06/10] arm_ffa: introduce sandbox FF-A support
  2023-03-28 16:11                                                                                         ` [PATCH v10 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
@ 2023-04-02  2:41                                                                                           ` Simon Glass
  2023-04-12  9:52                                                                                             ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-04-02  2:41 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, Ilias Apalodimas, Jens Wiklander, nd,
	Rob Herring, Sudeep Holla, Tom Rini, U-Boot Mailing List,
	Xueliang Zhong, Heinrich Schuchardt

Hi Abdellatif,

On Wed, 29 Mar 2023 at 05:12, Abdellatif El Khlifi <
abdellatif.elkhlifi@arm.com> wrote:
>
> 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>
> 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>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
>
> ---
> Changelog:
> ===============
>
> v10:
>
> * split the FF-A sandbox support into an emulator and a driver
> * read FFA_VERSION and FFA_PARTITION_INFO_GET state using
>    sandbox_ffa_query_core_state()
> * drop CONFIG_SANDBOX_FFA config
> * address nits
>
> v9: align FF-A sandbox driver with FF-A discovery through DM
>
> v8: update ffa_bus_prvdata_get() to return a pointer rather than
>     a pointer address
>
> v7: state that sandbox driver supports only 64-bit direct messaging
>
> v4: align sandbox driver with the new FF-A driver interfaces
>     and new way of error handling
>
> v1: introduce the sandbox driver
>
>  MAINTAINERS                                   |   3 +-
>  arch/sandbox/dts/sandbox.dtsi                 |   8 +
>  arch/sandbox/dts/test.dts                     |   8 +
>  arch/sandbox/include/asm/sandbox_arm_ffa.h    |  68 ++
>  .../include/asm/sandbox_arm_ffa_priv.h        | 133 ++++
>  configs/sandbox64_defconfig                   |   1 +
>  configs/sandbox_defconfig                     |   1 +
>  doc/arch/arm64.ffa.rst                        |   7 +-
>  doc/arch/sandbox/sandbox.rst                  |   1 +
>  drivers/firmware/arm-ffa/Kconfig              |  13 +-
>  drivers/firmware/arm-ffa/Makefile             |  10 +-
>  drivers/firmware/arm-ffa/ffa-emul-uclass.c    | 732 ++++++++++++++++++
>  .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |  14 -
>  drivers/firmware/arm-ffa/sandbox_ffa.c        | 108 +++
>  include/dm/uclass-id.h                        |   1 +
>  15 files changed, 1087 insertions(+), 21 deletions(-)
>  create mode 100644 arch/sandbox/include/asm/sandbox_arm_ffa.h
>  create mode 100644 arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
>  create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
>  delete mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
>  create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
>

[..]

> +/**
> + * sandbox_ffa_get_fwk_version() - Return the FFA framework version
> + * @dev: The sandbox FF-A emulator device
> + * @func_data:  Pointer to the FF-A function arguments container
structure
> + *
> + * Return the FFA framework version read from the FF-A emulator data.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int sandbox_ffa_get_fwk_version(struct udevice *dev, struct
ffa_sandbox_data *func_data)
> +{
> +       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
> +
> +       if (!func_data)
> +               return -EINVAL;
> +
> +       if (!func_data->data0 ||
> +           func_data->data0_size != sizeof(priv->fwk_version))
> +               return -EINVAL;
> +
> +       *((u32 *)func_data->data0) = priv->fwk_version;
> +
> +       return 0;
> +}
> +
> +/**
> + * sandbox_ffa_get_parts() - Return the address of partitions data
> + * @dev: The sandbox FF-A emulator device
> + * @func_data:  Pointer to the FF-A function arguments container
structure
> + *
> + * Return the address of partitions data read from the FF-A emulator
data.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int sandbox_ffa_get_parts(struct udevice *dev, struct
ffa_sandbox_data *func_data)
> +{
> +       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
> +
> +       if (!func_data)
> +               return -EINVAL;
> +
> +       if (!func_data->data0 ||
> +           func_data->data0_size != sizeof(struct ffa_partitions *))
> +               return -EINVAL;
> +
> +       *((struct ffa_partitions **)func_data->data0) = &priv->partitions;
> +
> +       return 0;
> +}
> +
> +/**
> + * sandbox_ffa_query_core_state() - Inspect the FF-A ABIs
> + * @queried_func_id:   The FF-A function to be queried
> + * @func_data:  Pointer to the FF-A function arguments container
structure
> + *
> + * Queries the status of FF-A ABI specified in the input argument.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int sandbox_ffa_query_core_state(u32 queried_func_id,
> +                                struct ffa_sandbox_data *func_data)
> +{
> +       struct udevice *dev;

Please can you use 'emul' for the emulator so it is separate from the
device?

> +
> +       uclass_first_device(UCLASS_FFA_EMUL, &dev);
> +       if (!dev) {
> +               log_err("[FFA][SANDBOX][Emul] Cannot find FF-A emulator
during querying state\n");
> +               return -ENODEV;
> +       }

How about storing the emulator somewhere? You could have:

struct sandbox_ffa_priv {
   struct udevice *emul;
};

.priv = sizeof(sandbox_ffa_priv)

> +
> +       switch (queried_func_id) {
> +       case FFA_RXTX_MAP:
> +       case FFA_RXTX_UNMAP:
> +       case FFA_RX_RELEASE:
> +               return sandbox_ffa_get_rxbuf_flags(dev, queried_func_id,
func_data);
> +       case FFA_VERSION:
> +               return sandbox_ffa_get_fwk_version(dev, func_data);
> +       case FFA_PARTITION_INFO_GET:
> +               return sandbox_ffa_get_parts(dev, func_data);
> +       default:
> +               log_err("[FFA][Sandbox][Emul] Undefined FF-A interface
(%d)\n",
> +                       queried_func_id);
> +               return -EINVAL;
> +       }
> +}
> +
> +/**
> + * sandbox_arm_ffa_smccc_smc() - FF-A SMC call emulation
> + * @args:      the SMC call arguments
> + * @res:       the SMC call returned data
> + *
> + * Emulates the FF-A ABIs SMC call.
> + * The emulated FF-A ABI is identified and invoked.
> + * FF-A emulation is based on the FF-A specification 1.0
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure.
> + * FF-A protocol error codes are returned using the registers arguments
as
> + * described by the specification
> + */
> +void sandbox_arm_ffa_smccc_smc(ffa_value_t args, ffa_value_t *res)
> +{
> +       int ret = 0;
> +       struct udevice *dev;
> +
> +       uclass_first_device(UCLASS_FFA_EMUL, &dev);
> +       if (!dev) {
> +               log_err("[FFA][SANDBOX][Emul] Cannot find FF-A emulator
during SMC emulation\n");
> +               return;
> +       }
> +
> +       switch (args.a0) {
> +       case FFA_SMC_32(FFA_VERSION):
> +               ret = sandbox_ffa_version(dev, &args, res);
> +               break;
> +       case FFA_SMC_32(FFA_PARTITION_INFO_GET):
> +               ret = sandbox_ffa_partition_info_get(dev, &args, res);
> +               break;
> +       case FFA_SMC_32(FFA_RXTX_UNMAP):
> +               ret = sandbox_ffa_rxtx_unmap(dev, &args, res);
> +               break;
> +       case FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ):
> +               ret = sandbox_ffa_msg_send_direct_req(dev, &args, res);
> +               break;
> +       case FFA_SMC_32(FFA_ID_GET):
> +               ret = sandbox_ffa_id_get(dev, &args, res);
> +               break;
> +       case FFA_SMC_32(FFA_FEATURES):
> +               ret = sandbox_ffa_features(&args, res);
> +               break;
> +       case FFA_SMC_64(FFA_RXTX_MAP):
> +               ret = sandbox_ffa_rxtx_map(dev, &args, res);
> +               break;
> +       case FFA_SMC_32(FFA_RX_RELEASE):
> +               ret = sandbox_ffa_rx_release(dev, &args, res);
> +               break;
> +       default:
> +               log_err("[FFA][Sandbox][Emul] Undefined FF-A interface
(0x%lx)\n",
> +                       args.a0);
> +       }
> +
> +       if (ret != 0)
> +               log_err("[FFA][Sandbox][Emul] FF-A ABI internal failure
(%d)\n", ret);
> +}
> +
> +/**
> + * ffa_emul_find() - Finds the FF-A emulator
> + * @dev:       the sandbox FF-A device (sandbox-arm-ffa)
> + * @emulp:     the FF-A emulator device (sandbox-ffa-emul)
> + *
> + * Searches for the FF-A emulator and returns its device pointer.
> + *
> + * Return:
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_emul_find(struct udevice *dev, struct udevice **emulp)
> +{
> +       if (!emulp)
> +               return -EINVAL;
> +
> +       *emulp = NULL;
> +
> +       uclass_first_device(UCLASS_FFA_EMUL, emulp);
> +       if (!(*emulp)) {
> +               log_err("[FFA][SANDBOX][Emul] Cannot find FF-A
emulator\n");
> +               return -ENODEV;
> +       }
> +
> +       log_info("[FFA][Sandbox][Emul] FF-A emulator found\n");
> +
> +       return 0;
> +}
> +
> +UCLASS_DRIVER(ffa_emul) = {
> +       .name           = "ffa_emul",
> +       .id             = UCLASS_FFA_EMUL,
> +};
> +
> +/* Sandbox Arm FF-A emulator operations */
> +
> +static const struct ffa_emul_ops sandbox_ffa_emul_ops = {
> +       .invoke_ffa_fn = sandbox_arm_ffa_smccc_smc,
> +};
> +
> +static const struct udevice_id sandbox_ffa_emul_ids[] = {
> +       { .compatible = "sandbox,arm-ffa-emul" },
> +       { }
> +};
> +
> +/* Declaring the sandbox FF-A emulator under UCLASS_FFA_EMUL */
> +U_BOOT_DRIVER(sandbox_ffa_emul) = {
> +       .name           = "sandbox_ffa_emul",
> +       .id             = UCLASS_FFA_EMUL,
> +       .of_match       = sandbox_ffa_emul_ids,
> +       .ops            = &sandbox_ffa_emul_ops,
> +       .priv_auto      = sizeof(struct sandbox_ffa_emul),
> +};
> diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> deleted file mode 100644
> index 4338f9c9b1..0000000000
> --- a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> +++ /dev/null
> @@ -1,14 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0+ */
> -/*
> - * Copyright 2022-2023 Arm Limited and/or its affiliates <
open-source-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..bb150fd5cd
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/sandbox_ffa.c
> @@ -0,0 +1,108 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2022-2023 Arm Limited and/or its affiliates <
open-source-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;
> +
> +/**
> + * ffa_set_smc_conduit() - Set the SMC conduit
> + *
> + * Selects the SMC conduit by setting the FF-A ABI invoke function.
> + * The function emulating the SMC call is provided by the FF-A emulator.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_set_smc_conduit(void)
> +{
> +       struct udevice *emul;
> +       int ret;
> +
> +       ret = ffa_emul_find(NULL, &emul);
> +       if (ret) {
> +               log_err("[FFA][Sandbox] Cannot find FF-A emulator, SMC
emulation failure\n");
> +               return -ENODEV;
> +       }
> +
> +       if (!ffa_emul_get_ops(emul)->invoke_ffa_fn) {
> +               log_err("[FFA][Sandbox] Cannot get FF-A emulator ops, SMC
emulation failure\n");
> +               return -ENOSYS;
> +       }
> +
> +       dscvry_info.invoke_ffa_fn = ffa_emul_get_ops(emul)->invoke_ffa_fn;
> +       log_info("[FFA][Sandbox] Using emulated Arm SMC for FF-A
conduit\n");
> +
> +       return 0;
> +}
> +
> +/**
> + * sandbox_ffa_probe() - The sandbox FF-A driver probe function
> + * @dev:       the sandbox Arm FF-A bus device (sandbox-arm-ffa)
> + *
> + * Probing is done through ffa_do_probe()
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int sandbox_ffa_probe(struct udevice *dev)
> +{
> +       return ffa_do_probe(dev);

Move to a uclass pre_probe()  method.

> +}

Drop this. You can add it in the uclass as a child_pre_probe member.

> +
> +/**
> + * sandbox_ffa_bind() - The sandbox FF-A driver bind function
> + * @dev:       the sandbox-arm-ffa device
> + * Tries to discover the emulated FF-A bus.
> + * Return:
> + *
> + * 0 on success.
> + */
> +static int sandbox_ffa_bind(struct udevice *dev)
> +{
> +       bool ret;
> +
> +       log_info("[FFA][Sandbox] binding the device\n");
> +
> +       ret = ffa_try_discovery();

The code for this is immediately above. Just do that here, or make the
above function static and rename it.

> +       if (ret)
> +               return 0;
> +       else
> +               return -ENODEV;

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,
> +       .probe          = sandbox_ffa_probe,
> +       .bind           = sandbox_ffa_bind,
> +       .ops            = &sandbox_ffa_ops,
> +};
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index df77c7da58..4658411935 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -61,6 +61,7 @@ enum uclass_id {
>         UCLASS_ETH,             /* Ethernet device */
>         UCLASS_ETH_PHY,         /* Ethernet PHY device */
>         UCLASS_FFA,             /* Arm Firmware Framework for Armv8-A */
> +       UCLASS_FFA_EMUL,                /* sandbox FF-A device emulator */
>         UCLASS_FIRMWARE,        /* Firmware */
>         UCLASS_FPGA,            /* FPGA device */
>         UCLASS_FUZZING_ENGINE,  /* Fuzzing engine */
> --
> 2.25.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 04/10] arm_ffa: introduce Arm FF-A support
  2023-03-28 16:11                                                                                         ` [PATCH v10 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-04-02  2:41                                                                                           ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-04-02  2:41 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, Ilias Apalodimas, Jens Wiklander, nd,
	Rob Herring, Sudeep Holla, Tom Rini, U-Boot Mailing List,
	Xueliang Zhong, Heinrich Schuchardt

Hi Abdellatif,

On Wed, 29 Mar 2023 at 05:12, Abdellatif El Khlifi <
abdellatif.elkhlifi@arm.com> wrote:
>
> Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0
>
> The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World leveraging TrustZone
> technology.
>
> This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> querying the FF-A framework from the secure world.
>
> The driver uses SMC32 calling convention which means using the first
> 32-bit data of the Xn registers.
>
> All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
> which has 64-bit version supported.
>
> Both 32-bit and 64-bit direct messaging are supported which allows both
> 32-bit and 64-bit clients to use the FF-A bus.
>
> FF-A is a discoverable bus and similar to architecture features.
> FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> by the PSCI driver.
>
> Clients are able to probe then use the FF-A bus by calling the DM class
> searching APIs (e.g: uclass_first_device).
>
> The Secure World is considered as one entity to communicate with
> using the FF-A bus. FF-A communication is handled by one device and
> one instance (the bus). This FF-A driver takes care of all the
> interactions between Normal world and Secure World.
>
> The driver exports its operations to be used by upper layers.
>
> Exported operations:
>
> - ffa_partition_info_get
> - ffa_sync_send_receive
> - ffa_rxtx_unmap
>
> 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 please refer to the driver documentation [2].
>
> [1]: https://developer.arm.com/documentation/den0077/latest/
> [2]: doc/arch/arm64.ffa.rst
>
> 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>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
>
> ---
> Changelog:
> ===============
>
> v10:
>
> * provide the driver operations through the Uclass
> * move the generic FF-A methods to the Uclass
> * keep Arm specific methods in the Arm driver (arm-ffa.c)
> * rename core.c to arm-ffa.c
> * address nits

The functions at the bottom like ffa_do_remove() should be changed to
uclass methods.

E.g.

.pre_remove = ffa_do_remove,
.pre_probe = ffa_do_probe
.post_bind = ffa_do_unbind

You can make them static and they don't need to called from elsewhere. It
is automatic.

- no need to check for !dev since this is the caller's responsibiliy
- no need to check for !priv since this cannot happen

It looks like you are using 'priv' as per-device uclass data. So instead,
please add something like:

per_device_auto = sizeof(struct ffa_priv)

in your uclass driver, then use dev_get_uclass_priv() instead of
dev_get_priv().

You should use the var name uc_priv instead of priv, so it is clear that
this relates to the uclass (i.e. is common across all devices in that
uclass)

You should almost never need to set the priv data, since driver model
handles this.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2023-03-28 16:11                                                                                         ` [PATCH v10 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
@ 2023-04-02  2:41                                                                                           ` Simon Glass
  2023-04-03  9:59                                                                                             ` Ilias Apalodimas
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-04-02  2:41 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, Ilias Apalodimas, Jens Wiklander, nd,
	Rob Herring, Sudeep Holla, Tom Rini, U-Boot Mailing List,
	Xueliang Zhong

Hi Abdellatif,

On Wed, 29 Mar 2023 at 05:12, Abdellatif El Khlifi <
abdellatif.elkhlifi@arm.com> wrote:
>
> turn on EFI MM communication
>
> On corstone1000 platform MM communication between u-boot
> and the secure world (Optee) is done using the FF-A bus.
>
> 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>
>
> ---
> Changelog:
> ===============
>
> v9: update copyright string
>
> v8:
>
> * drop OP-TEE configs from Corstone-1000 defconfig
>
> v7:
>
> * improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
>   FFA_SHARED_MM_BUFFER_OFFSET
> * update FFA_SHARED_MM_BUFFER_ADDR value
>
> v6:
>
> * corstone-1000: enable optee driver
> * corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig
>
> v4:
>
> * corstone-1000: turn on EFI MM communication
>
>  configs/corstone1000_defconfig |  2 ++
>  include/configs/corstone1000.h | 15 +++++++++++++--
>  2 files changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/configs/corstone1000_defconfig
b/configs/corstone1000_defconfig
> index 74250c7524..a7bfcbb2b9 100644
> --- a/configs/corstone1000_defconfig
> +++ b/configs/corstone1000_defconfig
> @@ -52,3 +52,5 @@ CONFIG_DM_SERIAL=y
>  CONFIG_USB=y
>  CONFIG_USB_ISP1760=y
>  CONFIG_ERRNO_STR=y
> +CONFIG_EFI_MM_COMM_TEE=y
> +CONFIG_ARM_FFA_TRANSPORT=y
> diff --git a/include/configs/corstone1000.h
b/include/configs/corstone1000.h
> index 3347c11792..4ef1f05e40 100644
> --- a/include/configs/corstone1000.h
> +++ b/include/configs/corstone1000.h
> @@ -1,9 +1,11 @@
>  /* SPDX-License-Identifier: GPL-2.0+ */
>  /*
> - * (C) Copyright 2022 ARM Limited
>   * (C) Copyright 2022 Linaro
>   * Rui Miguel Silva <rui.silva@linaro.org>
> - * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + * Copyright 2022-2023 Arm Limited and/or its affiliates <
open-source-office@arm.com>
> + *
> + * Authors:
> + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   *
>   * Configuration for Corstone1000. Parts were derived from other ARM
>   * configurations.
> @@ -14,6 +16,15 @@
>
>  #include <linux/sizes.h>
>
> +#define FFA_SHARED_MM_BUFFER_SIZE      SZ_4K /* 4 KB */
> +
> +/*
> + * shared buffer physical address used for communication between
> + * u-boot and the MM SP
> + */
> +#define FFA_SHARED_MM_BUFFER_ADDR      0x02000000UL
> +#define FFA_SHARED_MM_BUFFER_OFFSET    0
> +
>  #define V2M_BASE               0x80000000
>
>  #define CFG_PL011_CLOCK        50000000
> --
> 2.25.1
>

As a higher-level question, could this whole FFA implementation code be put
into Linux or fwupd?

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2023-04-02  2:41                                                                                           ` Simon Glass
@ 2023-04-03  9:59                                                                                             ` Ilias Apalodimas
  2023-04-03 10:33                                                                                               ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-04-03  9:59 UTC (permalink / raw)
  To: Simon Glass
  Cc: Abdellatif El Khlifi, Drew.Reed, achin.gupta, Jens Wiklander, nd,
	Rob Herring, Sudeep Holla, Tom Rini, U-Boot Mailing List,
	Xueliang Zhong

On Sun, Apr 02, 2023 at 02:41:17PM +1200, Simon Glass wrote:
> Hi Abdellatif,
>
> On Wed, 29 Mar 2023 at 05:12, Abdellatif El Khlifi <
> abdellatif.elkhlifi@arm.com> wrote:
> >
> > turn on EFI MM communication
> >
> > On corstone1000 platform MM communication between u-boot
> > and the secure world (Optee) is done using the FF-A bus.
> >
> > 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>
> >
> > ---
> > Changelog:
> > ===============
> >
> > v9: update copyright string
> >
> > v8:
> >
> > * drop OP-TEE configs from Corstone-1000 defconfig
> >
> > v7:
> >
> > * improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
> >   FFA_SHARED_MM_BUFFER_OFFSET
> > * update FFA_SHARED_MM_BUFFER_ADDR value
> >
> > v6:
> >
> > * corstone-1000: enable optee driver
> > * corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig
> >
> > v4:
> >
> > * corstone-1000: turn on EFI MM communication
> >
> >  configs/corstone1000_defconfig |  2 ++
> >  include/configs/corstone1000.h | 15 +++++++++++++--
> >  2 files changed, 15 insertions(+), 2 deletions(-)
> >
> > diff --git a/configs/corstone1000_defconfig
> b/configs/corstone1000_defconfig
> > index 74250c7524..a7bfcbb2b9 100644
> > --- a/configs/corstone1000_defconfig
> > +++ b/configs/corstone1000_defconfig
> > @@ -52,3 +52,5 @@ CONFIG_DM_SERIAL=y
> >  CONFIG_USB=y
> >  CONFIG_USB_ISP1760=y
> >  CONFIG_ERRNO_STR=y
> > +CONFIG_EFI_MM_COMM_TEE=y
> > +CONFIG_ARM_FFA_TRANSPORT=y
> > diff --git a/include/configs/corstone1000.h
> b/include/configs/corstone1000.h
> > index 3347c11792..4ef1f05e40 100644
> > --- a/include/configs/corstone1000.h
> > +++ b/include/configs/corstone1000.h
> > @@ -1,9 +1,11 @@
> >  /* SPDX-License-Identifier: GPL-2.0+ */
> >  /*
> > - * (C) Copyright 2022 ARM Limited
> >   * (C) Copyright 2022 Linaro
> >   * Rui Miguel Silva <rui.silva@linaro.org>
> > - * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + * Copyright 2022-2023 Arm Limited and/or its affiliates <
> open-source-office@arm.com>
> > + *
> > + * Authors:
> > + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   *
> >   * Configuration for Corstone1000. Parts were derived from other ARM
> >   * configurations.
> > @@ -14,6 +16,15 @@
> >
> >  #include <linux/sizes.h>
> >
> > +#define FFA_SHARED_MM_BUFFER_SIZE      SZ_4K /* 4 KB */
> > +
> > +/*
> > + * shared buffer physical address used for communication between
> > + * u-boot and the MM SP
> > + */
> > +#define FFA_SHARED_MM_BUFFER_ADDR      0x02000000UL
> > +#define FFA_SHARED_MM_BUFFER_OFFSET    0
> > +
> >  #define V2M_BASE               0x80000000
> >
> >  #define CFG_PL011_CLOCK        50000000
> > --
> > 2.25.1
> >
>
> As a higher-level question, could this whole FFA implementation code be put
> into Linux or fwupd?

Hi Simon, FF-A is basically a communication mechanism between the secure
and non-secure world for Arm.  Linux has support for it.  fwupd should be
completely agnostic to the protocol

Regards
/Ilias
>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2023-04-03  9:59                                                                                             ` Ilias Apalodimas
@ 2023-04-03 10:33                                                                                               ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-03 10:33 UTC (permalink / raw)
  To: sjg; +Cc: ilias.apalodimas, nd, u-boot

On Mon, Apr 03, 2023 at 12:59:06PM +0300, Ilias Apalodimas wrote:
> On Sun, Apr 02, 2023 at 02:41:17PM +1200, Simon Glass wrote:
> > Hi Abdellatif,
> >
> > On Wed, 29 Mar 2023 at 05:12, Abdellatif El Khlifi <
> > abdellatif.elkhlifi@arm.com> wrote:
> > >
> > > turn on EFI MM communication
> > >
> > > On corstone1000 platform MM communication between u-boot
> > > and the secure world (Optee) is done using the FF-A bus.
> > >
> > > 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>
> > >
> > > ---
> > > Changelog:
> > > ===============
> > >
> > > v9: update copyright string
> > >
> > > v8:
> > >
> > > * drop OP-TEE configs from Corstone-1000 defconfig
> > >
> > > v7:
> > >
> > > * improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
> > >   FFA_SHARED_MM_BUFFER_OFFSET
> > > * update FFA_SHARED_MM_BUFFER_ADDR value
> > >
> > > v6:
> > >
> > > * corstone-1000: enable optee driver
> > > * corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig
> > >
> > > v4:
> > >
> > > * corstone-1000: turn on EFI MM communication
> > >
> > >  configs/corstone1000_defconfig |  2 ++
> > >  include/configs/corstone1000.h | 15 +++++++++++++--
> > >  2 files changed, 15 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/configs/corstone1000_defconfig
> > b/configs/corstone1000_defconfig
> > > index 74250c7524..a7bfcbb2b9 100644
> > > --- a/configs/corstone1000_defconfig
> > > +++ b/configs/corstone1000_defconfig
> > > @@ -52,3 +52,5 @@ CONFIG_DM_SERIAL=y
> > >  CONFIG_USB=y
> > >  CONFIG_USB_ISP1760=y
> > >  CONFIG_ERRNO_STR=y
> > > +CONFIG_EFI_MM_COMM_TEE=y
> > > +CONFIG_ARM_FFA_TRANSPORT=y
> > > diff --git a/include/configs/corstone1000.h
> > b/include/configs/corstone1000.h
> > > index 3347c11792..4ef1f05e40 100644
> > > --- a/include/configs/corstone1000.h
> > > +++ b/include/configs/corstone1000.h
> > > @@ -1,9 +1,11 @@
> > >  /* SPDX-License-Identifier: GPL-2.0+ */
> > >  /*
> > > - * (C) Copyright 2022 ARM Limited
> > >   * (C) Copyright 2022 Linaro
> > >   * Rui Miguel Silva <rui.silva@linaro.org>
> > > - * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > + * Copyright 2022-2023 Arm Limited and/or its affiliates <
> > open-source-office@arm.com>
> > > + *
> > > + * Authors:
> > > + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > >   *
> > >   * Configuration for Corstone1000. Parts were derived from other ARM
> > >   * configurations.
> > > @@ -14,6 +16,15 @@
> > >
> > >  #include <linux/sizes.h>
> > >
> > > +#define FFA_SHARED_MM_BUFFER_SIZE      SZ_4K /* 4 KB */
> > > +
> > > +/*
> > > + * shared buffer physical address used for communication between
> > > + * u-boot and the MM SP
> > > + */
> > > +#define FFA_SHARED_MM_BUFFER_ADDR      0x02000000UL
> > > +#define FFA_SHARED_MM_BUFFER_OFFSET    0
> > > +
> > >  #define V2M_BASE               0x80000000
> > >
> > >  #define CFG_PL011_CLOCK        50000000
> > > --
> > > 2.25.1
> > >
> >
> > As a higher-level question, could this whole FFA implementation code be put
> > into Linux or fwupd?
> 
> Hi Simon, FF-A is basically a communication mechanism between the secure
> and non-secure world for Arm.  Linux has support for it.  fwupd should be
> completely agnostic to the protocol

Hi Simon,

I'd like to add to Ilias's explanation the following helpful resources:

- The patchset cover letter for a high level overview of what FF-A is about [1].
- A closer look at the FF-A implementation in U-Boot the readme [2].

Cheers

[1]: https://lore.kernel.org/all/20230328161157.219375-1-abdellatif.elkhlifi@arm.com/
[2]: doc/arch/arm64.ffa.rst

> 
> Regards
> /Ilias
> >
> > Regards,
> > Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v11 00/10] introduce Arm FF-A support
  2023-03-28 16:11                                                                                       ` [PATCH v10 " Abdellatif El Khlifi
                                                                                                           ` (9 preceding siblings ...)
  2023-03-28 16:11                                                                                         ` [PATCH v10 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
@ 2023-04-12  9:42                                                                                         ` Abdellatif El Khlifi
  2023-04-12  9:42                                                                                           ` [PATCH v11 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                                                                             ` (11 more replies)
  10 siblings, 12 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:42 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong, Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].

FF-A describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World. These interfaces enable a pair of
software sandboxes to communicate with each other. A sandbox aka partition could
be a VM in the Normal or Secure world, an application in S-EL0, or a
Trusted OS in S-EL1.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

   => dm tree

    Class     Index  Probed  Driver                Name
   -----------------------------------------------------------
   ...
    firmware      0  [ + ]   psci                      |-- psci
    ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
   ...

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_get_device_by_name).

This implementation of the specification provides support for Aarch64.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

    - Discover the presence of secure partitions (SPs) of interest
    - Access an SP's service through communication protocols
      e.g. EFI MM communication protocol

The FF-A support provides the following features:

    - Being generic by design and can be used by any Arm 64-bit platform
    - A Uclass driver providing generic FF-A methods and driver operations
    - An Arm FF-A device driver
    - FF-A support can be compiled and used without EFI
    - Support for SMCCCv1.2 x0-x17 registers
    - Support for SMC32 calling convention
    - Support for 32-bit and 64-bit FF-A direct messaging
    - A new command called armffa is provided as an example of how to access the
      FF-A bus
    - Support for FF-A MM communication (compatible with EFI boot time)
    - Enabling FF-A and MM communication in Corstone1000 platform as a use case
    - A sandbox emulator for Arm FF-A
    - An FF-A sandbox device driver
    - Sandbox FF-A test cases

For more details about the FF-A support please refer to [B] and refer to [C] for
how to use the armffa command.

Please find at [D] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of the major changes:
===========================

v11:

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* use U_BOOT_CMD_WITH_SUBCMDS for armffa command
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device
* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* use ut_asserteq_mem() in uuid_str_to_le_bin test case
* address nits

v10: [10]

* provide the FF-A driver operations through the Uclass (arm-ffa-uclass.c)
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c renamed from core.c)
* split the FF-A sandbox support into an emulator (ffa-emul-uclass.c) and a driver (sandbox_ffa.c)
* use the FF-A driver Uclass operations by clients (armffa command, tests, MM comms)
* use uclass_first_device to search and probe the FF-A device (whether it is on Arm or on sandbox)
* address nits

v9: [9]

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
* align FF-A sandbox driver with FF-A discovery through DM
* use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
* add documentation for the armffa command: doc/usage/cmd/armffa.rst
* introduce testcase for uuid_str_to_le_bin

v8: [8]

* pass the FF-A bus device to the bus operations
* isolate the compilation choices between FF-A and OP-TEE
* drop OP-TEE configs from Corstone-1000 defconfig
* make ffa_get_partitions_info() second argument to be an SP count in both
  modes

v7: [7]

* add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v6: [6]

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

List of previous patches:

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
[7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
[8]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
[9]: https://lore.kernel.org/all/20230310141016.137986-1-abdellatif.elkhlifi@arm.com/
[10]: https://lore.kernel.org/all/20230328161157.219375-1-abdellatif.elkhlifi@arm.com/

More details:

[A]: https://developer.arm.com/documentation/den0077/latest/
[B]: doc/arch/arm64.ffa.rst
[C]: doc/usage/cmd/armffa.rst
[D]: example of boot logs when enabling FF-A

```
   U-Boot 2023.01 (Mar 27 2023 - 13:48:33 +0000) corstone1000 aarch64

   DRAM:  2 GiB
   Arm FF-A framework discovery
   Using Arm SMC for FF-A conduit
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   ...
   Hit any key to stop autoboot:  0
   Loading kernel from 0x083EE000 to memory ...
   ...
   FF-A endpoint ID is 0
   Using 1 4KB page(s) for FF-A RX/TX buffers size
   FF-A RX buffer at virtual address 00000000fdf4f000
   FF-A TX buffer at virtual address 00000000fdf51000
   FF-A RX/TX buffers mapped
   Reading FF-A partitions data from the RX buffer
   FF-A partition ID 8001 : info cached
   FF-A partition ID 8002 : info cached
   FF-A partition ID 8003 : info cached
   3 FF-A partition(s) found and cached
   Preparing for checking FF-A partitions count
   Searching FF-A partitions using the provided UUID
   No FF-A partition found. Querying framework ...
   Reading FF-A partitions data from the RX buffer
   Number of FF-A partition(s) matching the UUID: 1
   EFI: Pre-allocating 1 partition(s) info structures
   Preparing for filling FF-A partitions info
   Searching FF-A partitions using the provided UUID
   FF-A partition ID 8003 matches the provided UUID
   EFI: MM partition ID 0x8003
   EFI: Corstone1000: Capsule shared buffer at 0x80000000 , size 8192 pages
   Booting /MemoryMapped(0x0,0x88200000,0xf00000)
   EFI stub: Booting Linux Kernel...
   EFI stub: Using DTB from configuration table
   EFI stub: Exiting boot services...
   unmapping FF-A RX/TX buffers
   Freeing FF-A RX/TX buffers
   Booting Linux on physical CPU 0x0000000000 [0x411fd040]
   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
   Machine model: ARM Corstone1000 FPGA MPS3 board
```

Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (10):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce uuid_str_to_le_bin function
  lib: uuid: introduce testcase for uuid_str_to_le_bin
  arm_ffa: introduce Arm FF-A support
  arm_ffa: introduce armffa command
  arm_ffa: introduce sandbox FF-A support
  arm_ffa: introduce sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   18 +
 arch/arm/cpu/armv8/smccc-call.S               |   57 +-
 arch/arm/lib/asm-offsets.c                    |   16 +
 arch/sandbox/dts/sandbox.dtsi                 |    8 +
 arch/sandbox/dts/test.dts                     |    8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |   72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        |  133 ++
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    2 +
 cmd/armffa.c                                  |  212 +++
 configs/corstone1000_defconfig                |    2 +
 configs/sandbox64_defconfig                   |    1 +
 configs/sandbox_defconfig                     |    1 +
 doc/arch/arm64.ffa.rst                        |  294 +++++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox/sandbox.rst                  |    1 +
 doc/usage/cmd/armffa.rst                      |  105 ++
 doc/usage/index.rst                           |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   42 +
 drivers/firmware/arm-ffa/Makefile             |   16 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1143 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  127 ++
 drivers/firmware/arm-ffa/ffa-emul-uclass.c    |  738 +++++++++++
 drivers/firmware/arm-ffa/sandbox_ffa.c        |  119 ++
 include/arm_ffa.h                             |  217 ++++
 include/arm_ffa_priv.h                        |  271 ++++
 include/configs/corstone1000.h                |   15 +-
 include/dm/uclass-id.h                        |    7 +
 include/linux/arm-smccc.h                     |   45 +
 include/mm_communication.h                    |   13 +
 include/uuid.h                                |   15 +
 lib/efi_loader/Kconfig                        |   14 +-
 lib/efi_loader/efi_variable_tee.c             |  312 ++++-
 lib/uuid.c                                    |   48 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   39 +
 test/dm/Makefile                              |    2 +
 test/dm/ffa.c                                 |  258 ++++
 test/lib/Makefile                             |    1 +
 test/lib/uuid.c                               |   41 +
 42 files changed, 4420 insertions(+), 9 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 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 doc/usage/cmd/armffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/lib/uuid.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v11 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-04-12  9:42                                                                                           ` Abdellatif El Khlifi
  2023-04-12  9:42                                                                                           ` [PATCH v11 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
                                                                                                             ` (10 subsequent siblings)
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:42 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>

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

v9:

* update the copyright string

v7:

* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

 arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
 arch/arm/lib/asm-offsets.c      | 16 +++++++++
 include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..93f66d3366 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,7 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
- */
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+*/
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
 #include <generated/asm-offsets.h>
@@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 6de0ce9152..181a8ac4c2 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,11 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * 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>
@@ -90,6 +95,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#ifdef CONFIG_ARM64
+	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..f44e9e8f93 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +74,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v11 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2023-04-12  9:42                                                                                           ` [PATCH v11 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-04-12  9:42                                                                                           ` Abdellatif El Khlifi
  2023-04-12  9:42                                                                                           ` [PATCH v11 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
                                                                                                             ` (9 subsequent siblings)
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:42 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong

convert UUID string to little endian binary data

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
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>

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

v9:

* add a full function prototype description in uuid.h

v8:

* use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

 include/uuid.h | 15 +++++++++++++++
 lib/uuid.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..89b93e642b 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,10 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +48,15 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ * Return:
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 96e1af3c8b..45f325d964 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * 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>
@@ -354,6 +358,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16;
+	u32 tmp32;
+	u64 tmp64;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+	memcpy(uuid_bin, &tmp32, 4);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16));
+	memcpy(uuid_bin + 10, &tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v11 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2023-04-12  9:42                                                                                           ` [PATCH v11 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2023-04-12  9:42                                                                                           ` [PATCH v11 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2023-04-12  9:42                                                                                           ` Abdellatif El Khlifi
  2023-04-19  1:46                                                                                             ` Simon Glass
  2023-04-12  9:42                                                                                           ` [PATCH v11 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                             ` (8 subsequent siblings)
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:42 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong

provide a test case

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Simon Glass <sjg@chromium.org>

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

v11:

* use ut_asserteq_mem()

 MAINTAINERS       |  5 +++++
 test/lib/Makefile |  1 +
 test/lib/uuid.c   | 41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)
 create mode 100644 test/lib/uuid.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d2e245e5e9..086e4cb3df 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1607,3 +1607,8 @@ S:	Maintained
 F:	arch/arm/dts/ls1021a-twr-u-boot.dtsi
 F:	drivers/crypto/fsl/
 F:	include/fsl_sec.h
+
+UUID testing
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	test/lib/uuid.c
diff --git a/test/lib/Makefile b/test/lib/Makefile
index e0bd9e04e8..e75a263e6a 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_AES) += test_aes.o
 obj-$(CONFIG_GETOPT) += getopt.o
 obj-$(CONFIG_CRC8) += test_crc8.o
 obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o
+obj-$(CONFIG_LIB_UUID) += uuid.o
 else
 obj-$(CONFIG_SANDBOX) += kconfig_spl.o
 endif
diff --git a/test/lib/uuid.c b/test/lib/uuid.c
new file mode 100644
index 0000000000..e24331a136
--- /dev/null
+++ b/test/lib/uuid.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <uuid.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* test UUID */
+#define TEST_SVC_UUID	"ed32d533-4209-99e6-2d72-cdd998a79cc0"
+
+#define UUID_SIZE 16
+
+/* The UUID binary data (little-endian format) */
+static const u8 ref_uuid_bin[UUID_SIZE] = {
+	0x33, 0xd5, 0x32, 0xed,
+	0x09, 0x42, 0xe6, 0x99,
+	0x72, 0x2d, 0xc0, 0x9c,
+	0xa7, 0x98, 0xd9, 0xcd
+};
+
+static int lib_test_uuid_to_le(struct unit_test_state *uts)
+{
+	const char *uuid_str = TEST_SVC_UUID;
+	u8 ret_uuid_bin[UUID_SIZE] = {0};
+
+	ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin));
+	ut_asserteq_mem(ref_uuid_bin, ret_uuid_bin, UUID_SIZE);
+
+	return 0;
+}
+
+LIB_TEST(lib_test_uuid_to_le, 0);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v11 04/10] arm_ffa: introduce Arm FF-A support
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                             ` (2 preceding siblings ...)
  2023-04-12  9:42                                                                                           ` [PATCH v11 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-04-12  9:42                                                                                           ` Abdellatif El Khlifi
  2023-04-19  1:49                                                                                             ` Simon Glass
  2023-04-12  9:42                                                                                           ` [PATCH v11 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                                                                             ` (7 subsequent siblings)
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:42 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong, Heinrich Schuchardt

Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- ffa_partition_info_get
- ffa_sync_send_receive
- ffa_rxtx_unmap

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 please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

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

v11:

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* pass dev as an argument of arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* add emul field in struct ffa_discovery_info
* address nits

v10:

* provide the driver operations through the Uclass
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c)
* rename core.c to arm-ffa.c
* address nits

v9:

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding

v8:

* make ffa_get_partitions_info() second argument to be an SP count in both
  modes
* update ffa_bus_prvdata_get() to return a pointer rather than a pointer
  address
* remove packing from ffa_partition_info and ffa_send_direct_data structures
* pass the FF-A bus device to the bus operations

v7:

* add support for 32-bit direct messaging
* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* improve the declaration of error handling mapping
* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the U-Boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the U-Boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

 MAINTAINERS                                   |    8 +
 doc/arch/arm64.ffa.rst                        |  271 ++++
 doc/arch/index.rst                            |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   36 +
 drivers/firmware/arm-ffa/Makefile             |    8 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1143 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  127 ++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |   14 +
 include/arm_ffa.h                             |  217 ++++
 include/arm_ffa_priv.h                        |  271 ++++
 include/dm/uclass-id.h                        |    6 +
 13 files changed, 2104 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 086e4cb3df..76f0f276ce 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,6 +266,14 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+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>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..466e77e3cd
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,271 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Support
+================
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software sandboxes to
+communicate with each other. A sandbox aka partition could
+be a VM in the Normal or Secure world, an application in S-EL0, or a
+Trusted OS in S-EL1.
+
+The U-Boot FF-A support (the bus) implements the interfaces to communicate
+with partitions in the Secure world aka Secure partitions (SPs).
+
+The FF-A support specifically focuses on communicating with SPs that
+isolate portions of EFI runtime services that must run in a protected
+environment which is inaccessible by the Host OS or Hypervisor.
+Examples of such services are set/get variables.
+
+The FF-A support uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+At this stage of development only EFI boot time is supported.
+Runtime support will be added in future developments.
+
+The U-Boot FF-A support provides the following parts:
+
+- A Uclass driver providing generic FF-A methods.
+- An Arm FF-A driver providing Arm specific methods and reusing the Uclass methods.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the U-Boot FF-A support relies on FF-A
+specification v1.0 and uses SMC32 calling convention which means using
+the first 32-bit data of the Xn registers.
+
+At this stage we only need the FF-A v1.0 features.
+
+The FF-A support has been tested with OP-TEE which supports SMC32 calling
+convention.
+
+For more details please refer to the FF-A v1.0 spec:
+https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A support uses 64-bit registers as per SMCCCv1.2 specification.
+
+For more details please refer to the SMC Calling Convention v1.2 spec:
+https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+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.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers.
+Then, an SMC instruction is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-Boot Arm FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs.
+
+FF-A bus discovery on Arm 64-bit platforms
+---------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
+an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
+This discovery mechanism is performed by the PSCI driver.
+
+The PSCI driver comes with a PSCI device tree node which is the root node for all
+architecture features including FF-A bus.
+
+::
+
+   => dm tree
+
+    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.
+
+In case of FF-A, the callback is arm_ffa_is_supported() which tries to discover the
+FF-A framework by querying the FF-A framework version from secure world using
+FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
+mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver
+with the device using device_bind_driver().
+
+At this stage the FF-A bus is registered with the DM and can be interacted with using
+the DM APIs.
+
+Clients are able to probe then use the FF-A bus by calling uclass_first_device().
+Please refer to the armffa command implementation as an example of how to probe
+and interact with the FF-A bus.
+
+When calling uclass_first_device(), the FF-A driver is probed and ends up calling
+ffa_do_probe() provided by the Uclass which does the following:
+
+    - updating uc_priv with discovery information
+    - querying from secure world the u-boot endpoint ID
+    - querying from secure world the supported features of FFA_RXTX_MAP
+    - mapping the RX/TX buffers
+    - querying from secure world all the partitions information
+
+When one of the above actions fails, probing fails and the driver stays not active
+and can be probed again if needed.
+
+FF-A device destruction
+-------------------------
+
+When the FF-A device is removed by the DM, RX/TX buffers are automatically
+unmapped and freed.
+
+For example, at EFI efi_exit_boot_services() active devices are automatically removed
+by dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL).
+
+By consequence, the FF-A RX/TX are unmapped automatically.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must query the SPs they are looking for
+during EFI boot time mode using the service UUID.
+
+The RX/TX buffers are only available at EFI boot time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped before EFI runtime mode starts.
+The driver provides a bus operation for that called ffa_rxtx_unmap() and this is done
+automatically at efi_exit_boot_services().
+
+If  RX/TX buffers created by U-Boot are not unmapped and by consequence becoming
+available at EFI runtime, secure world will get confused about RX/TX buffers
+ownership (U-Boot vs kernel).
+
+When invoking FF-A direct messaging, clients should specify which ABI protocol
+they want to use (32-bit vs 64-bit). Selecting the protocol means using
+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
+The calling convention between U-Boot and the secure world stays the same: SMC32.
+
+The bus driver layer
+------------------------------
+
+FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c
+
+The following features are provided:
+
+- Support for the 32-bit version of the following ABIs:
+
+    - FFA_VERSION
+    - FFA_ID_GET
+    - FFA_FEATURES
+    - FFA_PARTITION_INFO_GET
+    - FFA_RXTX_UNMAP
+    - FFA_RX_RELEASE
+    - FFA_RUN
+    - FFA_ERROR
+    - FFA_SUCCESS
+    - FFA_INTERRUPT
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Support for the 64-bit version of the following ABIs:
+
+    - FFA_RXTX_MAP
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, FF-A support takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- FF-A support provides driver operations to be used by upper layers:
+
+    - ffa_partition_info_get
+    - ffa_sync_send_receive
+    - ffa_rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+Example of boot logs with FF-A enabled
+--------------------------------------
+
+For example, when using FF-A with Corstone-1000 the logs are as follows:
+
+::
+
+   U-Boot 2023.01 (Mar 27 2023 - 13:48:33 +0000) corstone1000 aarch64
+
+   DRAM:  2 GiB
+   Arm FF-A framework discovery
+   Using Arm SMC for FF-A conduit
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   ...
+   Hit any key to stop autoboot:  0
+   Loading kernel from 0x083EE000 to memory ...
+   ...
+   FF-A endpoint ID is 0
+   Using 1 4KB page(s) for FF-A RX/TX buffers size
+   FF-A RX buffer at virtual address 00000000fdf4f000
+   FF-A TX buffer at virtual address 00000000fdf51000
+   FF-A RX/TX buffers mapped
+   Reading FF-A partitions data from the RX buffer
+   FF-A partition ID 8001 : info cached
+   FF-A partition ID 8002 : info cached
+   FF-A partition ID 8003 : info cached
+   3 FF-A partition(s) found and cached
+   Preparing for checking FF-A partitions count
+   Searching FF-A partitions using the provided UUID
+   No FF-A partition found. Querying framework ...
+   Reading FF-A partitions data from the RX buffer
+   Number of FF-A partition(s) matching the UUID: 1
+   EFI: Pre-allocating 1 partition(s) info structures
+   Preparing for filling FF-A partitions info
+   Searching FF-A partitions using the provided UUID
+   FF-A partition ID 8003 matches the provided UUID
+   EFI: MM partition ID 0x8003
+   EFI: Corstone1000: Capsule shared buffer at 0x80000000 , size 8192 pages
+   Booting /MemoryMapped(0x0,0x88200000,0xf00000)
+   EFI stub: Booting Linux Kernel...
+   EFI stub: Using DTB from configuration table
+   EFI stub: Exiting boot services...
+   unmapping FF-A RX/TX buffers
+   Freeing FF-A RX/TX buffers
+   Booting Linux on physical CPU 0x0000000000 [0x411fd040]
+   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
+   Machine model: ARM Corstone1000 FPGA MPS3 board
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index b8da4b8c8e..2f916f4026 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Makefile b/drivers/Makefile
index 58be410135..885fdef4dc 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -112,6 +112,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index eae1c8ddc9..8789b1ea14 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
 	  the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
 	  services if any and reported as supported by the SMCCC firmware.
 
+source "drivers/firmware/arm-ffa/Kconfig"
 source "drivers/firmware/scmi/Kconfig"
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..9200c8028b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select ARM_SMCCC_FEATURES
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
+	  FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
+	  by the PSCI driver.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  The FF-A support on U-Boot  takes care of all the interactions between Normal
+	  world and Secure World.
+
+	  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
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..11b1766285
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,8 @@
+# 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>
+
+obj-y += arm-ffa-uclass.o arm-ffa.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..c3ad19b8e7
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,1143 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* FF-A discovery information */
+struct ffa_discovery_info dscvry_info;
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	[NOT_SUPPORTED] = -EOPNOTSUPP,
+	[INVALID_PARAMETERS] = -EINVAL,
+	[NO_MEMORY] = -ENOMEM,
+	[BUSY] = -EBUSY,
+	[INTERRUPTED] = -EINTR,
+	[DENIED] = -EACCES,
+	[RETRY] = -EAGAIN,
+	[ABORTED] = -ECANCELED,
+};
+
+static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			[NO_MEMORY] =
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			[BUSY] =
+			"BUSY: RX buffer of the caller is not free",
+			[DENIED] =
+			"DENIED: Callee is not in a state to handle this request",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			[DENIED] =
+			"DENIED: Caller did not have ownership of the RX buffer",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			[NO_MEMORY] =
+			"NO_MEMORY: Not enough memory",
+			[DENIED] =
+			"DENIED: Buffer pair already registered",
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno() - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+static int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* Map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+static int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* Map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	log_err("%s\n", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/* FF-A ABIs implementation (U-Boot side) */
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	if (!dscvry_info.invoke_ffa_fn)
+		return -EINVAL;
+
+	dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	log_info("FF-A driver %d.%d\nFF-A framework %d.%d\n",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) {
+		log_info("FF-A versions are compatible\n");
+
+		dscvry_info.fwk_version = res.a0;
+
+		return 0;
+	}
+
+	log_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id() - FFA_ID_GET handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	uc_priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		uc_priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		log_info("FF-A endpoint ID is %u\n", uc_priv->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt() - set the minimum number of pages in each of the RX/TX buffers
+ * @dev: The FF-A bus device
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * Set the minimum number of pages in each of the RX/TX buffers in uc_priv
+ *
+ * Return:
+ *
+ * buf_4k_pages points to the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	switch (prop_field) {
+	case RXTX_4K:
+		uc_priv->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		uc_priv->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		uc_priv->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		log_err("RX/TX buffer size not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features_hdlr() - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_FEATURES FF-A function to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	uc_priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers() - free the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Free the RX/TX buffers
+ */
+static void ffa_free_rxtx_buffers(struct udevice *dev)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_info("Freeing FF-A RX/TX buffers\n");
+
+	if (uc_priv->pair.rxbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+	}
+
+	if (uc_priv->pair.txbuf) {
+		free(uc_priv->pair.txbuf);
+		uc_priv->pair.txbuf = NULL;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers() - allocate the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(struct udevice *dev)
+{
+	u64 bytes;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_info("Using %lu 4KB page(s) for FF-A RX/TX buffers size\n",
+		 uc_priv->pair.rxtx_min_pages);
+
+	bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 * Assumption: Memory allocated with memalign is always physically contiguous
+	 */
+
+	uc_priv->pair.rxbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.rxbuf) {
+		log_err("failure to allocate RX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_info("FF-A RX buffer at virtual address %p\n", uc_priv->pair.rxbuf);
+
+	uc_priv->pair.txbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.txbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+		log_err("failure to allocate the TX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_info("FF-A TX buffer at virtual address %p\n", uc_priv->pair.txbuf);
+
+	/* Make sure the buffers are cleared before use */
+	memset(uc_priv->pair.rxbuf, 0, bytes);
+	memset(uc_priv->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers_hdlr() - FFA_RXTX_MAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_MAP FF-A function to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	ret = ffa_alloc_rxtx_buffers(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 * no need to convert from virtual to physical
+	 */
+
+	uc_priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = map_to_sysmem(uc_priv->pair.txbuf),
+			.a2 = map_to_sysmem(uc_priv->pair.rxbuf),
+			.a3 = uc_priv->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		log_info("FF-A RX/TX buffers mapped\n");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers(dev);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_UNMAP FF-A function to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = NULL;
+
+	log_info("unmapping FF-A RX/TX buffers\n");
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	uc_priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers(dev);
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer_hdlr() - FFA_RX_RELEASE handler function
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_RX_RELEASE FF-A function to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	uc_priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical() - check whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * Used by ffa_read_partitions_info to search for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+static bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+				   const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info() - read queried partition data
+ * @dev: The FF-A bus device
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * Read the partitions information returned by the FFA_PARTITION_INFO_GET and saves it in uc_priv
+ *
+ * Return:
+ *
+ * uc_priv is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(struct udevice *dev, u32 count,
+				    struct ffa_partition_uuid *part_uuid)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	if (!count) {
+		log_err("no partition detected\n");
+		return -ENODATA;
+	}
+
+	log_info("Reading FF-A partitions data from the RX buffer\n");
+
+	if (!part_uuid) {
+		/* Querying information of all partitions */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			log_err("partitions data size exceeds the RX buffer size:\n");
+			log_err("    sizes in bytes: data %llu , RX buffer %llu\n",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		uc_priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO);
+		if (!uc_priv->partitions.descs) {
+			log_err("cannot  allocate partitions data buffer\n");
+			return -ENOMEM;
+		}
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			uc_priv->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			log_info("FF-A partition ID %x : info cached\n",
+				 uc_priv->partitions.descs[desc_idx].info.id);
+		}
+
+		uc_priv->partitions.count = count;
+
+		log_info("%d FF-A partition(s) found and cached\n", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		/*
+		 * Search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/* Search the current ID in the cached partitions */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < uc_priv->partitions.count;
+			     cached_desc_idx++) {
+				/* Save the UUID */
+				if (uc_priv->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					uc_priv->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info() - invoke FFA_PARTITION_INFO_GET and save partitions data
+ * @dev: The FF-A bus device
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * Execute the FFA_PARTITION_INFO_GET to query the partitions data.
+ * Then, call ffa_read_partitions_info to save the data in uc_priv.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	uc_priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid);
+			if (ret) {
+				log_err("failed reading SP(s) data , err (%d)\n", ret);
+				ffa_release_rx_buffer_hdlr(dev);
+				return -EINVAL;
+			}
+		}
+
+		/* Return the SP count (when querying using a UUID) */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer_hdlr(dev);
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of partitions
+ *			 The variable will be set by the driver
+ *	@buffer: NULL
+ *
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@dev: The FF-A bus device
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of empty partition descriptors
+ *			 The variable will be read by the driver
+ *	@buffer: pointer to SPs information buffer
+ *		(allocated by the client and contains empty @sp_count descriptors).
+ *		The buffer will be filled by the driver
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * When invoked through a client request, ffa_get_partitions_info_hdlr() should be
+ * called twice. First call is to get from the driver the number of secure
+ * partitions (SPs) associated to a particular UUID.
+ * Then, the caller (client) allocates the buffer to host the SPs data and
+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
+ * buffer.
+ *
+ * To achieve the mechanism described above, ffa_get_partitions_info_hdlr() uses the
+ * following functions:
+ *		ffa_read_partitions_info
+ *		ffa_query_partitions_info
+ *
+ * Return:
+ *
+ * @sp_count: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer size, the buffer will be
+ * filled by the driver.
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_info *buffer)
+{
+	/*
+	 * fill_data:
+	 * 0: return the SP count
+	 * 1: fill SP data and return it to the caller
+	 */
+	bool fill_data = 0;
+	u32 desc_idx, client_desc_idx;
+	struct ffa_partition_uuid part_uuid = {0};
+	u32 sp_found = 0;
+	struct ffa_priv *uc_priv = NULL;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs) {
+		log_err("no partition installed\n");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		log_err("no UUID provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_count) {
+		log_err("no size/count provided\n");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		log_err("invalid UUID\n");
+		return -EINVAL;
+	}
+
+	if (!buffer) {
+		/* Mode 1: getting the number of secure partitions */
+
+		fill_data = 0;
+
+		log_info("Preparing for checking FF-A partitions count\n");
+
+	} else if (*sp_count) {
+		/* Mode 2: retrieving the partitions information */
+
+		fill_data = 1;
+
+		client_desc_idx = 0;
+
+		log_info("Preparing for filling FF-A partitions info\n");
+
+	} else {
+		log_err("invalid function arguments provided\n");
+		return -EINVAL;
+	}
+
+	log_info("Searching FF-A partitions using the provided UUID\n");
+
+	/* Search in the cached partitions */
+	for (desc_idx = 0;
+	     desc_idx < uc_priv->partitions.count;
+	     desc_idx++) {
+		if (ffa_uuid_are_identical(&uc_priv->partitions.descs[desc_idx].sp_uuid,
+					   &part_uuid)) {
+			log_info("FF-A partition ID %x matches the provided UUID\n",
+				 uc_priv->partitions.descs[desc_idx].info.id);
+
+			sp_found++;
+
+			if (fill_data) {
+				/* Trying to fill the partition info in the input buffer */
+
+				if (client_desc_idx < *sp_count) {
+					buffer[client_desc_idx++] =
+						uc_priv->partitions.descs[desc_idx].info;
+					continue;
+				}
+
+				log_err("failed to fill client descriptor, buffer full\n");
+				return -ENOBUFS;
+			}
+		}
+	}
+
+	if (!sp_found) {
+		int ret;
+
+		log_info("No FF-A partition found. Querying framework ...\n");
+
+		ret = ffa_query_partitions_info(dev, &part_uuid, &sp_found);
+
+		if (ret == 0) {
+			if (!fill_data) {
+				*sp_count = sp_found;
+
+				log_info("Number of FF-A partition(s) matching the UUID: %d\n",
+					 sp_found);
+			} else {
+				/*
+				 * If SPs data detected, they are already in uc_priv.
+				 * Retry searching SP data again to return them
+				 *  to the caller
+				 */
+				if (sp_found)
+					ret = ffa_get_partitions_info_hdlr(dev, uuid_str, sp_count,
+									   buffer);
+				else
+					ret = -ENODATA;
+			}
+		}
+
+		return ret;
+	}
+
+	/* Partition(s) found */
+	if (!fill_data)
+		*sp_count = sp_found;
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info() - Query and saves all secure partitions data
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_PARTITION_INFO_GET FF-A function to query from secure world
+ * all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in uc_priv
+ * and we keep the UUID field empty (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * Called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(struct udevice *dev)
+{
+	return ffa_query_partitions_info(dev, NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Implement FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u64 req_mode, resp_mode;
+	struct ffa_priv *uc_priv = NULL;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	if (!uc_priv->dscvry_info.invoke_ffa_fn)
+		return -EINVAL;
+
+	/* No partition installed */
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs)
+		return -ENODEV;
+
+	if (is_smc64) {
+		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+	} else {
+		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
+	}
+
+	uc_priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = req_mode,
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		uc_priv->dscvry_info.invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == resp_mode) {
+		/* Message sent with response extract the return data */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/* FF-A driver operations (used by clients for communicating with FF-A)*/
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ *
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of partitions
+ *			 The variable will be set by the driver
+ *	@buffer: NULL
+ *
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@dev: The FF-A bus device
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of empty partition descriptors
+ *			 The variable will be read by the driver
+ *	@buffer: pointer to SPs information buffer
+ *		(allocated by the client and contains empty @sp_count descriptors).
+ *		The buffer will be filled by the driver
+ *
+ * Driver operation for FFA_PARTITION_INFO_GET.
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * @sp_count: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer size, the buffer will be
+ * filled by the driver.
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_info *buffer)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->partition_info_get)
+		return -ENOSYS;
+
+	return ops->partition_info_get(dev, uuid_str, sp_count, buffer);
+}
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Driver operation for FFA_MSG_SEND_DIRECT_{REQ,RESP}.
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->sync_send_receive)
+		return -ENOSYS;
+
+	return ops->sync_send_receive(dev, dst_part_id, msg, is_smc64);
+}
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * @dev: The FF-A bus device
+ *
+ * Driver operation for FFA_RXTX_UNMAP.
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_rxtx_unmap(struct udevice *dev)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->rxtx_unmap)
+		return -ENOSYS;
+
+	return ops->rxtx_unmap(dev);
+}
+
+/**
+ * ffa_do_probe() - probing FF-A framework
+ * @dev:	the FF-A bus device (arm_ffa)
+ *
+ * Probing is triggered on demand by clients searching for the uclass.
+ * At probe level the following actions are done:
+ *	- updating uc_priv with discovery information
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in uc_priv.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_do_probe(struct udevice *dev)
+{
+	int ret;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	uc_priv->dscvry_info = dscvry_info;
+
+	ret = ffa_get_endpoint_id(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_cache_partitions_info(dev);
+	if (ret) {
+		ffa_unmap_rxtx_buffers_hdlr(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+UCLASS_DRIVER(ffa) = {
+	.name			= "ffa",
+	.id			= UCLASS_FFA,
+	.pre_probe		= ffa_do_probe,
+	.pre_remove		= ffa_unmap_rxtx_buffers_hdlr,
+	.per_device_auto	= sizeof(struct ffa_priv)
+};
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
new file mode 100644
index 0000000000..254f747010
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -0,0 +1,127 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <linux/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * __arm_ffa_fn_smc() - 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 low level SMC assembly function
+ */
+static void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * arm_ffa_set_smc() - Set the SMC conduit
+ * @dev: The Arm FF-A bus device (arm_ffa)
+ *
+ * Select the SMC conduit by setting the FF-A ABI invoke function
+ * to the function executing the SMC call.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int arm_ffa_set_smc(struct udevice *dev)
+{
+	dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc;
+	log_info("Using Arm SMC for FF-A conduit\n");
+
+	return 0;
+}
+
+/**
+ * arm_ffa_discover() - perform FF-A discovery
+ * @dev: The Arm FF-A bus device (arm_ffa)
+ * 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:
+ *
+ * true on success. Otherwise, false.
+ */
+static bool arm_ffa_discover(struct udevice *dev)
+{
+	int ret;
+
+	log_info("Arm FF-A framework discovery\n");
+
+	ret = arm_ffa_set_smc(dev);
+	if (ret)
+		return false;
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/**
+ * arm_ffa_is_supported() - FF-A bus discovery callback
+ * @invoke_fn: legacy SMC invoke function (not used)
+ *
+ * Perform FF-A discovery by calling arm_ffa_discover().
+ * Discovery is performed by querying the FF-A framework version from
+ * secure world using the FFA_VERSION ABI.
+ *
+ * The FF-A driver is registered as an SMCCC feature driver. So, features discovery
+ * callbacks are called by the PSCI driver (PSCI device is the SMCCC features
+ * root device).
+ *
+ * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
+ * So, the legacy SMC invocation is not used.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static bool arm_ffa_is_supported(void (*invoke_fn)(ulong a0, ulong a1,
+						   ulong a2, ulong a3,
+						   ulong a4, ulong a5,
+						   ulong a6, ulong a7,
+						   struct arm_smccc_res *res))
+{
+	return arm_ffa_discover(NULL);
+}
+
+/* Arm FF-A driver operations */
+
+static const struct ffa_bus_ops 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,
+};
+
+/* Registering the FF-A driver as an SMCCC feature driver */
+
+ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
+	.driver_name = FFA_DRV_NAME,
+	.is_supported = arm_ffa_is_supported,
+};
+
+/* Declaring the FF-A driver under UCLASS_FFA */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.flags		= DM_REMOVE_OS_PREPARE,
+	.ops		= &ffa_ops,
+};
diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
new file mode 100644
index 0000000000..4338f9c9b1
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
@@ -0,0 +1,14 @@
+/* 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/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..e14bc082f6
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,217 @@
+/* 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 __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct ffa_send_direct_data {
+	ulong data0; /* w3/x3 */
+	ulong data1; /* w4/x4 */
+	ulong data2; /* w5/x5 */
+	ulong data3; /* w6/x6 */
+	ulong data4; /* w7/x7 */
+};
+
+/* FF-A discovery information */
+extern struct ffa_discovery_info dscvry_info;
+
+struct udevice;
+
+/**
+ * struct ffa_bus_ops - Operations for FF-A
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
+				  u32 *sp_count, struct ffa_partition_info *buffer);
+	int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg,
+				 bool is_smc64);
+	int (*rxtx_unmap)(struct udevice *dev);
+};
+
+#define ffa_get_ops(dev)        ((struct ffa_bus_ops *)(dev)->driver->ops)
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ */
+int ffa_rxtx_unmap(struct udevice *dev);
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The arm_ffa bus device
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev);
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The arm_ffa bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_info *buffer);
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *
+ * The passed arguments:
+ * Mode 1: When getting from the driver the number of
+ *	secure partitions:
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of partitions
+ *			 The variable will be set by the driver
+ *	@buffer: NULL
+ *
+ * Mode 2: When requesting the driver to return the
+ *	partitions information:
+ *	@dev: The arm_ffa bus device
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: pointer to the variable that contains the number of empty partition descriptors
+ *			 The variable will be read by the driver
+ *	@buffer: pointer to SPs information buffer
+ *		(allocated by the client and contains empty @sp_count descriptors).
+ *		The buffer will be filled by the driver
+ *
+ * This function queries the secure partition data from
+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * When invoked through a client request, ffa_get_partitions_info_hdlr() should be
+ * called twice. First call is to get from the driver the number of secure
+ * partitions (SPs) associated to a particular UUID.
+ * Then, the caller (client) allocates the buffer to host the SPs data and
+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
+ * buffer.
+ *
+ * To achieve the mechanism described above, ffa_get_partitions_info_hdlr() uses the
+ * following functions:
+ *		ffa_read_partitions_info
+ *		ffa_query_partitions_info
+ *
+ * Return:
+ *
+ * @sp_count: When pointing to the number of partitions variable, the number is
+ * set by the driver.
+ * When pointing to the partitions information buffer size, the buffer will be
+ * filled by the driver.
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_info *buffer);
+
+struct ffa_priv;
+
+/**
+ * ffa_set_smc_conduit() - Set the SMC conduit
+ * @dev: The FF-A bus device
+ *
+ * Selects the SMC conduit by setting the FF-A ABI invoke function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_set_smc_conduit(struct udevice *dev);
+
+#endif
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
new file mode 100644
index 0000000000..8851b7b410
--- /dev/null
+++ b/include/arm_ffa_priv.h
@@ -0,0 +1,271 @@
+/* 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 __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <mapmem.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+
+/* This header is exclusively used by the FF-A Uclass and FF-A driver(s) */
+
+/* Arm FF-A driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* The FF-A SMC function definitions */
+
+#if CONFIG_IS_ENABLED(SANDBOX)
+
+/* Providing Arm SMCCC declarations to sandbox */
+
+/**
+ * struct sandbox_smccc_1_2_regs - emulated SMC call arguments or results
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct sandbox_smccc_1_2_regs {
+	ulong a0;
+	ulong a1;
+	ulong a2;
+	ulong a3;
+	ulong a4;
+	ulong a5;
+	ulong a6;
+	ulong a7;
+	ulong a8;
+	ulong a9;
+	ulong a10;
+	ulong a11;
+	ulong a12;
+	ulong a13;
+	ulong a14;
+	ulong a15;
+	ulong a16;
+	ulong a17;
+};
+
+typedef struct sandbox_smccc_1_2_regs ffa_value_t;
+
+#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))
+
+#else
+/* CONFIG_ARM64 */
+#include <linux/arm-smccc.h>
+typedef struct arm_smccc_1_2_regs ffa_value_t;
+#endif
+
+/* Defining the function pointer type for the function executing the FF-A ABIs */
+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)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR                 = 0x60,
+	FFA_SUCCESS               = 0x61,
+	FFA_INTERRUPT             = 0x62,
+	FFA_VERSION               = 0x63,
+	FFA_FEATURES              = 0x64,
+	FFA_RX_RELEASE            = 0x65,
+	FFA_RXTX_MAP              = 0x66,
+	FFA_RXTX_UNMAP            = 0x67,
+	FFA_PARTITION_INFO_GET    = 0x68,
+	FFA_ID_GET                = 0x69,
+	FFA_RUN                   = 0x6d,
+	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
+	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
+
+	/* To be updated when adding new FFA IDs */
+	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
+	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
+};
+
+enum ffa_abi_errcode {
+	NOT_SUPPORTED = 1,
+	INVALID_PARAMETERS,
+	NO_MEMORY,
+	BUSY,
+	INTERRUPTED,
+	DENIED,
+	RETRY,
+	ABORTED,
+	MAX_NUMBER_FFA_ERR
+};
+
+extern int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR];
+
+/* Container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
+
+/*
+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
+ * @a1-4:	32-bit words access to the UUID data
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Hosts the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	void *rxbuf; /* Virtual address returned by memalign */
+	void *txbuf; /* Virtual address returned by memalign */
+	size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * Contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* Virtual address */
+};
+
+/**
+ * struct ffa_discovery_info - discovery information
+ * @fwk_version:	FF-A framework version
+ * @invoke_ffa_fn:	The function executing the FF-A function (ABI)
+ * @emul:	FF-A sandbox emulator
+ */
+struct ffa_discovery_info {
+	u32 fwk_version;
+	invoke_ffa_fn_t invoke_ffa_fn;
+	struct udevice *emul;
+};
+
+/**
+ * struct ffa_priv - the driver private data structure
+ *
+ * @dscvry_info:	Initial information discovered
+ * @ops:	The driver operations structure
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ *
+ * The device private data structure containing all the
+ * data read from secure world.
+ * The data is dynamically allocated, managed by devres
+ * and registered with the DM.
+ */
+struct ffa_priv {
+	struct ffa_discovery_info dscvry_info;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+};
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 33e43c20db..df77c7da58 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,11 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -55,6 +60,7 @@ enum uclass_id {
 	UCLASS_EFI_MEDIA,	/* Devices provided by UEFI firmware */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v11 05/10] arm_ffa: introduce armffa command
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                             ` (3 preceding siblings ...)
  2023-04-12  9:42                                                                                           ` [PATCH v11 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-04-12  9:42                                                                                           ` Abdellatif El Khlifi
  2023-04-12 14:02                                                                                             ` Heinrich Schuchardt
  2023-04-19  1:49                                                                                             ` Simon Glass
  2023-04-12  9:42                                                                                           ` [PATCH v11 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
                                                                                                             ` (6 subsequent siblings)
  11 siblings, 2 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:42 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong, Heinrich Schuchardt

Provide armffa command showcasing the use of the U-Boot FF-A support

armffa is a command showcasing how to invoke FF-A operations.
This provides a guidance to the client developers on how to
call the FF-A bus interfaces. The command also allows to gather secure
partitions information and ping these  partitions. The command is also
helpful in testing the communication with secure partitions.

For more details please refer to the command documentation [1].

[1]: doc/usage/cmd/armffa.rst

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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

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

v11:

* use U_BOOT_CMD_WITH_SUBCMDS
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* address nits

v9:

* remove manual FF-A discovery and use DM
* use DM class APIs to probe and interact with the FF-A bus
* add doc/usage/cmd/armffa.rst

v8:

* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* adapt do_ffa_dev_list() following the recent update on
  uclass_first_device/uclass_next_device functions (they return void now)
* set armffa command to use 64-bit direct messaging

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

 MAINTAINERS                      |   2 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   2 +
 cmd/armffa.c                     | 212 +++++++++++++++++++++++++++++++
 doc/arch/arm64.ffa.rst           |   7 +
 doc/usage/cmd/armffa.rst         | 105 +++++++++++++++
 doc/usage/index.rst              |   1 +
 drivers/firmware/arm-ffa/Kconfig |   1 +
 8 files changed, 340 insertions(+)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/usage/cmd/armffa.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 76f0f276ce..c64804ca2d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,7 +269,9 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+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
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 8c9b430f99..4cb0b2c167 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -934,6 +934,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the FF-A support
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index e032091621..9130b9078d 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,8 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
 obj-$(CONFIG_CMD_AES) += aes.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..ab88412c7d
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,212 @@
+// 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 <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+#include <asm/io.h>
+
+/**
+ * ffa_get_dev() - Return the FF-A device
+ * @devp:	pointer to the FF-A device
+ *
+ * Search for the FF-A device.
+ *
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_dev(struct udevice **devp)
+{
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, devp);
+	if (ret) {
+		log_err("Cannot find FF-A bus device\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/**
+ * do_ffa_getpart() - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver
+ * partition_info_get operation which implements FFA_PARTITION_INFO_GET
+ * ABI to retrieve the data. The input UUID string is expected to be in big
+ * endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+	u32 i;
+	struct udevice *dev;
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	/* Mode 1: getting the number of secure partitions */
+	ret = ffa_partition_info_get(dev, argv[1], &count, NULL);
+	if (ret) {
+		log_err("Failure in querying partitions count (error code: %d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	if (!count) {
+		log_info("No secure partition found\n");
+		return CMD_RET_FAILURE;
+	}
+
+	/*
+	 * Pre-allocate a buffer to be filled by the driver
+	 * with ffa_partition_info structs
+	 */
+
+	log_info("Pre-allocating %d partition(s) info structures\n", count);
+
+	parts_info = calloc(count, sizeof(struct ffa_partition_info));
+	if (!parts_info)
+		return CMD_RET_FAILURE;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+
+	ret = ffa_partition_info_get(dev, argv[1], &count, parts_info);
+	if (ret) {
+		log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
+		free(parts_info);
+		return CMD_RET_FAILURE;
+	}
+
+	/* SPs found , show the partition information */
+	for (i = 0; i < count ; i++) {
+		log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
+			 parts_info[i].id,
+			 parts_info[i].exec_ctxt,
+			 parts_info[i].properties);
+	}
+
+	free(parts_info);
+
+	return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_ffa_ping() - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Send data to the secure partition which the ID is provided
+ * as an argument. Use the arm_ffa driver sync_send_receive operation
+ * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+	struct udevice *dev;
+
+	errno = 0;
+	part_id = strtoul(argv[1], NULL, 16);
+
+	if (errno) {
+		log_err("Invalid partition ID\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	if (!ret) {
+		u8 cnt;
+
+		log_info("SP response:\n[LSB]\n");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			log_info("%llx\n", ((u64 *)&msg)[cnt]);
+		return CMD_RET_SUCCESS;
+	}
+
+	log_err("Sending direct request error (%d)\n", ret);
+	return CMD_RET_FAILURE;
+}
+
+/**
+ *do_ffa_devlist() - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query the device belonging to the UCLASS_FFA
+ * class.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	log_info("device name %s, dev %p, driver name %s, ops %p\n",
+		 dev->name,
+		(void *)map_to_sysmem(dev),
+		 dev->driver->name,
+		 (void *)map_to_sysmem(dev->driver->ops));
+
+	return CMD_RET_SUCCESS;
+}
+
+static char armffa_help_text[] =
+	"getpart <partition UUID>\n"
+	"       - lists the partition(s) info\n"
+	"ping <partition ID>\n"
+	"       - sends a data pattern to the specified partition\n"
+	"devlist\n"
+	"       - displays information about the FF-A device/driver\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
+			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
+			U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping),
+			U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist));
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 466e77e3cd..ed7240aef7 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -216,6 +216,13 @@ The following features are provided:
 
 - FF-A bus can be compiled and used without EFI
 
+The armffa command
+-----------------------------------
+
+armffa is an implementation defined command showcasing how to use the FF-A bus and how to invoke the driver operations.
+
+Please refer the command documentation at doc/usage/cmd/armffa.rst
+
 Example of boot logs with FF-A enabled
 --------------------------------------
 
diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
new file mode 100644
index 0000000000..e73d03ae51
--- /dev/null
+++ b/doc/usage/cmd/armffa.rst
@@ -0,0 +1,105 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+armffa command
+==============
+
+Synopsis
+--------
+
+::
+
+   armffa [sub-command] [arguments]
+
+   sub-commands:
+
+        getpart [partition UUID]
+
+            lists the partition(s) info
+
+        ping [partition ID]
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays information about the FF-A device/driver
+
+Description
+-----------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
+
+The command also allows to gather secure partitions information and ping these  partitions.
+
+The command is also helpful in testing the communication with secure partitions.
+
+Example
+-------
+
+The following examples are run on Corstone-1000 platform with debug logs enabled.
+
+* ping
+
+::
+
+   corstone1000# armffa ping 0x8003
+   SP response:
+   [LSB]
+   fffffffe
+   0
+   0
+   0
+   0
+
+* ping (failure case)
+
+::
+
+   corstone1000# armffa ping 0
+   Sending direct request error (-22)
+
+* getpart
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
+   Preparing for checking FF-A partitions count
+   Searching FF-A partitions using the provided UUID
+   No FF-A partition found. Querying framework ...
+   Reading FF-A partitions data from the RX buffer
+   Number of FF-A partition(s) matching the UUID: 1
+   Pre-allocating 1 partition(s) info structures
+   Preparing for filling FF-A partitions info
+   Searching FF-A partitions using the provided UUID
+   FF-A partition ID 8003 matches the provided UUID
+   Partition: id = 8003 , exec_ctxt 1 , properties 3
+
+* getpart (failure case)
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221
+   Preparing for checking FF-A partitions count
+   Searching FF-A partitions using the provided UUID
+   No FF-A partition found. Querying framework ...
+   INVALID_PARAMETERS: Unrecognized UUID
+   Failure in querying partitions count (error code: -22)
+
+* devlist
+
+::
+
+   corstone1000# armffa devlist
+   device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98
+
+Configuration
+-------------
+
+The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
+
+Return value
+------------
+
+The return value $? is 0 (true) on success and a negative error code on failure.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index bc85e1d49a..df107fb710 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -21,6 +21,7 @@ Shell commands
 
    cmd/acpi
    cmd/addrmap
+   cmd/armffa
    cmd/askenv
    cmd/base
    cmd/bdinfo
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index 9200c8028b..a7d5392859 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
 	depends on DM && ARM64
 	select ARM_SMCCC
 	select ARM_SMCCC_FEATURES
+	imply CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v11 06/10] arm_ffa: introduce sandbox FF-A support
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                             ` (4 preceding siblings ...)
  2023-04-12  9:42                                                                                           ` [PATCH v11 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-04-12  9:42                                                                                           ` Abdellatif El Khlifi
  2023-04-19  1:49                                                                                             ` Simon Glass
  2023-04-12  9:42                                                                                           ` [PATCH v11 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                                                                             ` (5 subsequent siblings)
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:42 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong, Heinrich Schuchardt

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>
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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

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

v11:

* rename ffa_try_discovery() to sandbox_ffa_discover()
* rename sandbox_ffa_query_core_state() to sandbox_query_ffa_emul_state()
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device

v10:

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

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

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

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

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

v1: introduce the sandbox driver

 MAINTAINERS                                   |   3 +-
 arch/sandbox/dts/sandbox.dtsi                 |   8 +
 arch/sandbox/dts/test.dts                     |   8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |  72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        | 133 ++++
 configs/sandbox64_defconfig                   |   1 +
 configs/sandbox_defconfig                     |   1 +
 doc/arch/arm64.ffa.rst                        |  21 +-
 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    | 738 ++++++++++++++++++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |  14 -
 drivers/firmware/arm-ffa/sandbox_ffa.c        | 119 +++
 include/dm/uclass-id.h                        |   1 +
 15 files changed, 1120 insertions(+), 23 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 c64804ca2d..d7caad3bd4 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..ac713800d1 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -445,6 +445,14 @@
 	thermal {
 		compatible = "sandbox,thermal";
 	};
+
+	arm-ffa-emul {
+		compatible = "sandbox,arm-ffa-emul";
+	};
+
+	sandbox-arm-ffa {
+		compatible = "sandbox,arm-ffa";
+	};
 };
 
 &cros_ec {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index d72d7a567a..bd42906159 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1802,6 +1802,14 @@
 		compatible = "u-boot,fwu-mdata-gpt";
 		fwu-mdata-store = <&mmc0>;
 	};
+
+	arm-ffa-emul {
+		compatible = "sandbox,arm-ffa-emul";
+	};
+
+	sandbox-arm-ffa {
+		compatible = "sandbox,arm-ffa";
+	};
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/arch/sandbox/include/asm/sandbox_arm_ffa.h b/arch/sandbox/include/asm/sandbox_arm_ffa.h
new file mode 100644
index 0000000000..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..8fbfa3760d
--- /dev/null
+++ b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
@@ -0,0 +1,133 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-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;
+};
+
+/**
+ * struct ffa_emul_ops - Operations for the FF-A emulator
+ * @invoke_ffa_fn:	callback for the emulated SMC call
+ *
+ * Provides all the operations supported by the FF-A emulator.
+ */
+struct ffa_emul_ops {
+	void (*invoke_ffa_fn)(ffa_value_t args, ffa_value_t *res);
+};
+
+#define ffa_emul_get_ops(dev)        ((struct ffa_emul_ops *)(dev)->driver->ops)
+
+/**
+ * ffa_emul_find() - Finds the FF-A emulator
+ * @dev:	the sandbox FF-A device (sandbox-arm-ffa)
+ * @emulp:	the FF-A emulator device (sandbox-ffa-emul)
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+int ffa_emul_find(struct udevice *dev, struct udevice **emulp);
+
+#endif
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index af2c56ad4c..3a0371557c 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -260,3 +260,4 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index cbace259f8..dda668046a 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -339,3 +339,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index ed7240aef7..431c29f921 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -33,7 +33,11 @@ Runtime support will be added in future developments.
 The U-Boot FF-A support provides the following parts:
 
 - A Uclass driver providing generic FF-A methods.
-- An Arm FF-A driver providing Arm specific methods and reusing the Uclass methods.
+- An Arm FF-A device driver providing Arm specific methods and reusing the Uclass methods.
+- A sandbox emulator for Arm FF-A, emulates the FF-A side of the Secure World and provides
+  FF-A ABIs inspection methods.
+- An FF-A sandbox device driver for FF-A communication with the emulated Secure World.
+  The driver leverages the FF-A Uclass to establish FF-A communication.
 
 FF-A and SMC specifications
 -------------------------------------------
@@ -69,6 +73,7 @@ CONFIG_ARM_FFA_TRANSPORT
     Enables the FF-A support. Turn this on if you want to use FF-A
     communication.
     When using an Arm 64-bit platform, the Arm FF-A driver will be used.
+    When using sandbox, the sandbox FF-A emulator and FF-A sandbox driver will be used.
 
 FF-A ABIs under the hood
 ---------------------------------------
@@ -105,10 +110,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.
@@ -216,6 +219,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 cd7f8a2cb0..c5df372e00 100644
--- a/doc/arch/sandbox/sandbox.rst
+++ b/doc/arch/sandbox/sandbox.rst
@@ -200,6 +200,7 @@ Supported Drivers
 
 U-Boot sandbox supports these emulations:
 
+- Arm FF-A
 - Block devices
 - Chrome OS EC
 - GPIO
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index a7d5392859..d75f8b53fd 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -2,9 +2,9 @@
 
 config ARM_FFA_TRANSPORT
 	bool "Enable Arm Firmware Framework for Armv8-A driver"
-	depends on DM && ARM64
-	select ARM_SMCCC
-	select ARM_SMCCC_FEATURES
+	depends on DM && (ARM64 || SANDBOX)
+	select ARM_SMCCC if !SANDBOX
+	select ARM_SMCCC_FEATURES if !SANDBOX
 	imply CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
@@ -33,5 +33,10 @@ config ARM_FFA_TRANSPORT
 	  Generic FF-A methods are implemented in the Uclass (arm-ffa-uclass.c).
 	  Arm specific methods are implemented in the Arm driver (arm-ffa.c).
 
-	  For more details about the FF-A support, please refer to doc/arch/arm64.ffa.rst
+	  FF-A sandbox is provided to run FF-A under sandbox and allows to test the FF-A Uclass.
+	  Sandbox support includes an emulator for Arm FF-A which emulates the FF-A side of
+	  the Secure World and provides FF-A ABIs inspection methods (ffa-emul-uclass.c).
+	  An FF-A sandbox driver is also provided for FF-A communication with the emulated
+	  Secure World (sandbox_ffa.c).
 
+	  For more details about the FF-A support, please refer to doc/arch/arm64.ffa.rst
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
index 11b1766285..318123a7f4 100644
--- a/drivers/firmware/arm-ffa/Makefile
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -5,4 +5,12 @@
 # Authors:
 #   Abdellatif El Khlifi <abdellatif.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..f12bae4820
--- /dev/null
+++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
@@ -0,0 +1,738 @@
+// 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_SP2_ID, .exec_ctxt = 0x9587,
+			  .properties = 0x45325621 },
+		.sp_uuid = {
+			.a1 = SANDBOX_SERVICE2_UUID_A1,
+			.a2 = SANDBOX_SERVICE2_UUID_A2,
+			.a3 = SANDBOX_SERVICE2_UUID_A3,
+			.a4 = SANDBOX_SERVICE2_UUID_A4,
+		}
+	},
+	{
+		.info = { .id = SANDBOX_SP3_ID, .exec_ctxt = 0x7687,
+			  .properties = 0x23325621 },
+		.sp_uuid = {
+			.a1 = SANDBOX_SERVICE1_UUID_A1,
+			.a2 = SANDBOX_SERVICE1_UUID_A2,
+			.a3 = SANDBOX_SERVICE1_UUID_A3,
+			.a4 = SANDBOX_SERVICE1_UUID_A4,
+		}
+	},
+	{
+		.info = { .id = SANDBOX_SP4_ID, .exec_ctxt = 0x1487,
+			  .properties = 0x70325621 },
+		.sp_uuid = {
+			.a1 = SANDBOX_SERVICE2_UUID_A1,
+			.a2 = SANDBOX_SERVICE2_UUID_A2,
+			.a3 = SANDBOX_SERVICE2_UUID_A3,
+			.a4 = SANDBOX_SERVICE2_UUID_A4,
+		}
+	}
+
+};
+
+/* The emulator functions */
+
+/**
+ * sandbox_ffa_version() - Emulated FFA_VERSION handler function
+ * @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 -ENODEV;
+	}
+
+	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);
+}
+
+/**
+ * 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 -ENODEV;
+	}
+
+	/* the emulator device should be destroyed last */
+	ret = device_reparent(dev, *emulp);
+	if (ret) {
+		log_err("Cannot set FF-A emulator as parent\n");
+		return -ENODEV;
+	}
+
+	log_info("FF-A emulator ready to use\n");
+
+	return 0;
+}
+
+UCLASS_DRIVER(ffa_emul) = {
+	.name		= "ffa_emul",
+	.id		= UCLASS_FFA_EMUL,
+};
+
+/* Sandbox Arm FF-A emulator operations */
+
+static const struct ffa_emul_ops sandbox_ffa_emul_ops = {
+	.invoke_ffa_fn = sandbox_arm_ffa_smccc_smc,
+};
+
+static const struct udevice_id sandbox_ffa_emul_ids[] = {
+	{ .compatible = "sandbox,arm-ffa-emul" },
+	{ }
+};
+
+/* Declaring the sandbox FF-A emulator under UCLASS_FFA_EMUL */
+U_BOOT_DRIVER(sandbox_ffa_emul) = {
+	.name		= "sandbox_ffa_emul",
+	.id		= UCLASS_FFA_EMUL,
+	.of_match	= sandbox_ffa_emul_ids,
+	.ops		= &sandbox_ffa_emul_ops,
+	.priv_auto	= sizeof(struct sandbox_ffa_emul),
+};
diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
deleted file mode 100644
index 4338f9c9b1..0000000000
--- a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-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..2398305404
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox_ffa.c
@@ -0,0 +1,119 @@
+// 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_set_smc() - Set the SMC conduit
+ * @dev: the sandbox-arm-ffa device
+ *
+ * Select the SMC conduit by setting the FF-A ABI invoke function.
+ * The function emulating the SMC call is provided by the FF-A emulator.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_set_smc(struct udevice *dev)
+{
+	struct udevice *emul;
+	int ret;
+
+	ret = ffa_emul_find(dev, &emul);
+	if (ret) {
+		log_err("Cannot find FF-A emulator, SMC emulation failure\n");
+		return -ENODEV;
+	}
+
+	if (!ffa_emul_get_ops(emul)->invoke_ffa_fn) {
+		log_err("Cannot get FF-A emulator ops, SMC emulation failure\n");
+		return -ENOSYS;
+	}
+
+	dscvry_info.emul = emul;
+	dscvry_info.invoke_ffa_fn = ffa_emul_get_ops(emul)->invoke_ffa_fn;
+
+	log_info("Using emulated Arm SMC for FF-A conduit\n");
+
+	return 0;
+}
+
+/**
+ * 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;
+
+	log_info("Emulated FF-A framework discovery\n");
+
+	ret = sandbox_ffa_set_smc(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		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,
+	.ops		= &sandbox_ffa_ops,
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index df77c7da58..4658411935 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -61,6 +61,7 @@ enum uclass_id {
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
+	UCLASS_FFA_EMUL,		/* sandbox FF-A device emulator */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v11 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                             ` (5 preceding siblings ...)
  2023-04-12  9:42                                                                                           ` [PATCH v11 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
@ 2023-04-12  9:42                                                                                           ` Abdellatif El Khlifi
  2023-04-19  1:50                                                                                             ` Simon Glass
  2023-04-12  9:42                                                                                           ` [PATCH v11 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                                                                             ` (4 subsequent siblings)
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:42 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong, Heinrich Schuchardt

Add functional test cases for the FF-A support

These tests rely on the FF-A sandbox emulator and FF-A
sandbox driver which help in inspecting the FF-A communication.

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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

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

v11:

* drop unmapping test (taken care of by the DM when removing the device)
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT
* address nits

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

v8:

  * update partition_info_get() second argument to be an SP count
  * pass NULL device pointer to the FF-A bus discovery and operations

v7: set the tests to use 64-bit direct messaging

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

v1: introduce sandbox tests

 MAINTAINERS            |   1 +
 doc/arch/arm64.ffa.rst |   1 +
 test/dm/Makefile       |   2 +
 test/dm/ffa.c          | 258 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 262 insertions(+)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d7caad3bd4..cd99e655db 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 431c29f921..fdcb008d72 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -38,6 +38,7 @@ The U-Boot FF-A support provides the following parts:
   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.
+- Sandbox FF-A test cases.
 
 FF-A and SMC specifications
 -------------------------------------------
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 7a79b6e1a2..45563bdfb4 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -85,6 +86,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..ace2582e22
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <console.h>
+#include <dm.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <asm/sandbox_arm_ffa_priv.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Functional tests for the UCLASS_FFA */
+
+static int check_fwk_version(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	struct ffa_sandbox_data func_data;
+	u32 fwk_version = 0;
+
+	func_data.data0 = &fwk_version;
+	func_data.data0_size = sizeof(fwk_version);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_VERSION, &func_data));
+	ut_asserteq(uc_priv->dscvry_info.fwk_version, fwk_version);
+
+	return 0;
+}
+
+static int check_endpoint_id(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_asserteq(0, uc_priv->id);
+
+	return 0;
+}
+
+static int check_rxtxbuf(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assertnonnull(uc_priv->pair.rxbuf);
+	ut_assertnonnull(uc_priv->pair.txbuf);
+
+	return 0;
+}
+
+static int check_features(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assert(uc_priv->pair.rxtx_min_pages == RXTX_4K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_16K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_64K);
+
+	return 0;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+		ut_asserteq(1, rxbuf_mapped);
+		break;
+	case FFA_RXTX_UNMAP:
+		ut_asserteq(0, rxbuf_mapped);
+		break;
+	default:
+		ut_assert(false);
+	}
+
+	return 0;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	ut_asserteq(0, rxbuf_owned);
+
+	return 0;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg;
+	u8 cnt;
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]);
+
+	return 0;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct unit_test_state *uts)
+{
+	struct ffa_partition_info parts_info[SANDBOX_SP_COUNT_PER_VALID_SERVICE] = {0};
+	u32 count, info_idx, exp_info_idx, valid_sps = 0;
+	struct udevice *dev;
+	struct ffa_sandbox_data func_data;
+	struct ffa_partitions *partitions;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get from the driver the count of the SPs matching the UUID */
+	ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, NULL));
+	/* Make sure partitions are detected */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, parts_info));
+
+	/* SPs found , verify the partitions information */
+
+	func_data.data0 = &partitions;
+	func_data.data0_size = sizeof(struct ffa_partitions *);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_PARTITION_INFO_GET, &func_data));
+
+	for (info_idx = 0; info_idx < count ; info_idx++) {
+		for (exp_info_idx = 0;
+		     exp_info_idx < partitions->count;
+		     exp_info_idx++) {
+			if (parts_info[info_idx].id ==
+			   partitions->descs[exp_info_idx].info.id) {
+				valid_sps++;
+				ut_asserteq_mem(&parts_info[info_idx],
+						&partitions->descs[exp_info_idx]
+						.info,
+						sizeof(struct ffa_partition_info));
+				/* Send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
+			}
+		}
+	}
+
+	/* Verify expected partitions found in the emulated secure world */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, valid_sps);
+
+	return 0;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	struct ffa_sandbox_data func_data;
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	struct udevice *dev;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Test FFA_VERSION */
+	check_fwk_version(uc_priv, uts);
+
+	/* Test FFA_ID_GET */
+	check_endpoint_id(uc_priv, uts);
+
+	/* Test FFA_FEATURES */
+	check_features(uc_priv, uts);
+
+	/*  Test RX/TX buffers */
+	check_rxtxbuf(uc_priv, uts);
+
+	/* Test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	sandbox_query_ffa_emul_state(FFA_RXTX_MAP, &func_data);
+	check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc1_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data);
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc2_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data));
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg;
+	int ret;
+	u32 count;
+	u16 part_id = 0;
+	struct udevice *dev;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Query partitions count using  invalid arguments */
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID  string */
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid_str, &count, NULL);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, NULL);
+	ut_assertok(count);
+
+	/* Query partitions count using a valid UUID */
+	count = 0;
+	ut_assertok(ffa_partition_info_get(dev, valid_svc_uuid, &count, NULL));
+	/* Make sure partitions are detected */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+
+	/* Send data to an invalid partition */
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Send data to a valid partition */
+	part_id = uc_priv->partitions.descs[0].info.id;
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v11 08/10] arm_ffa: introduce armffa command Sandbox test
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                             ` (6 preceding siblings ...)
  2023-04-12  9:42                                                                                           ` [PATCH v11 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-04-12  9:42                                                                                           ` Abdellatif El Khlifi
  2023-04-19  1:50                                                                                             ` Simon Glass
  2023-04-12  9:42                                                                                           ` [PATCH v11 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
                                                                                                             ` (3 subsequent siblings)
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:42 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong

Add Sandbox test for the armffa command

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
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>

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

v10:

* replace CMD_RET_SUCCESS with 0
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT

v9: align the test with FF-A discovery through DM

v4: drop use of helper APIs

v1: introduce armffa command sandbox test

 MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 39 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index cd99e655db..67eed92a9b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 055adc65a2..1d1dbb4fbc 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -23,6 +24,7 @@ obj-$(CONFIG_CMD_SEAMA) += seama.o
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_CMD_READ) += rw.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o
 endif
 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
 obj-$(CONFIG_CMD_WGET) += wget.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..a9768dbd2c
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * 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 <string.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define PING_CMD_SIZE 19
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	char ping_cmd[PING_CMD_SIZE] = {0};
+
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	snprintf(ping_cmd, PING_CMD_SIZE, "armffa ping 0x%x", SANDBOX_SP1_ID);
+
+	/* armffa ping <ID> */
+	ut_assertok(run_command(ping_cmd, 0));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return 0;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v11 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                             ` (7 preceding siblings ...)
  2023-04-12  9:42                                                                                           ` [PATCH v11 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2023-04-12  9:42                                                                                           ` Abdellatif El Khlifi
  2023-04-19  1:49                                                                                             ` Simon Glass
  2023-04-21  8:10                                                                                             ` Ilias Apalodimas
  2023-04-12  9:42                                                                                           ` [PATCH v11 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
                                                                                                             ` (2 subsequent siblings)
  11 siblings, 2 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:42 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong, Gowtham Suresh Kumar

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

MM communication protocol supports FF-A 64-bit direct messaging.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>

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

v11:

* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* addressing nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* addressing nits

v9: align how FF-A is used with FF-A discovery through DM

v8:

* isolate the compilation choices between FF-A and OP-TEE
* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make mm_sp_svc_uuid static
* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
* improve use of unmap_sysmem() in ffa_mm_communicate()

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

 include/mm_communication.h        |  13 ++
 lib/efi_loader/Kconfig            |  14 +-
 lib/efi_loader/efi_variable_tee.c | 312 +++++++++++++++++++++++++++++-
 3 files changed, 333 insertions(+), 6 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..f17847583b 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,9 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *    Authors:
+ *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +16,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
@@ -248,4 +254,11 @@ struct smm_variable_var_check_property {
 	u16                       name[];
 };
 
+/* supported MM transports */
+enum mm_comms_select {
+	MM_COMMS_UNDEFINED,
+	MM_COMMS_FFA,
+	MM_COMMS_OPTEE
+};
+
 #endif /* _MM_COMMUNICATION_H_ */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c5835e6ef6..08a6b84101 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	depends on OPTEE || ARM_FFA_TRANSPORT
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..a6ec126db5 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,9 +4,14 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  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 <efi.h>
 #include <efi_api.h>
 #include <efi_loader.h>
@@ -15,6 +20,36 @@
 #include <malloc.h>
 #include <mm_communication.h>
 
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+#include <arm_ffa.h>
+#include <cpu_func.h>
+#include <mapmem.h>
+
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_SIZE 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_OFFSET
+#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_OFFSET 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_ADDR 0
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+
+static const char *mm_sp_svc_uuid = MM_SP_UUID;
+
+static u16 mm_sp_id;
+
+#endif
+
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -24,6 +59,7 @@ struct mm_connection {
 	u32 session;
 };
 
+#if (IS_ENABLED(CONFIG_OPTEE))
 /**
  * get_connection() - Retrieve OP-TEE session for a specific UUID.
  *
@@ -60,6 +96,7 @@ static int get_connection(struct mm_connection *conn)
 out:
 	return rc;
 }
+#endif
 
 /**
  * optee_mm_communicate() - Pass a buffer to StandaloneMM running in OP-TEE
@@ -70,6 +107,7 @@ out:
  */
 static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 {
+#if (IS_ENABLED(CONFIG_OPTEE))
 	ulong buf_size;
 	efi_status_t ret;
 	struct efi_mm_communicate_header *mm_hdr;
@@ -142,19 +180,269 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 	}
 
 	return ret;
+#else
+	log_err("EFI: Please enable CONFIG_OPTEE for MM comms\n");
+	return EFI_UNSUPPORTED;
+#endif
+}
+
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+
+/**
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notify the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret = -1;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
+		return -ENODEV;
+	}
+
+	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
+
+	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
+	if (ret)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	if (sp_event_ret == MM_SUCCESS)
+		return 0;
+
+	/* Failure to notify the MM SP */
+
+	return -EACCES;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_info *parts_info;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
+		return -ENODEV;
+	}
+
+	/* Get from the driver the count of the SPs matching the UUID */
+	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, NULL);
+	if (ret) {
+		log_err("EFI: Failure in querying SPs count (%d), MM SP discovery failure\n", ret);
+		return ret;
+	}
+
+	if (!count) {
+		log_info("EFI: No MM partition found\n");
+		return ret;
+	}
+
+	/* Pre-allocate a buffer to be filled by the driver with ffa_partition_info structs */
+
+	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
+
+	parts_info = calloc(count, sizeof(*parts_info));
+	if (!parts_info)
+		return -ENOMEM;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, parts_info);
+	if (ret) {
+		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
+		free(parts_info);
+		return ret;
+	}
+
+	/* MM SPs found , use the first one */
+
+	mm_sp_id = parts_info[0].id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	free(parts_info);
+
+	return 0;
+}
+#endif
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+	ulong tx_data_size;
+	int ffa_ret;
+	efi_status_t efi_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()) {
+		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+
+	switch (ffa_ret) {
+	case 0: {
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		efi_ret = EFI_SUCCESS;
+		break;
+	}
+	case -EINVAL:
+		efi_ret = EFI_DEVICE_ERROR;
+		break;
+	case -EPERM:
+		efi_ret = EFI_INVALID_PARAMETER;
+		break;
+	case -EACCES:
+		efi_ret = EFI_ACCESS_DENIED;
+		break;
+	case -EBUSY:
+		efi_ret = EFI_OUT_OF_RESOURCES;
+		break;
+	default:
+		efi_ret = EFI_ACCESS_DENIED;
+	}
+
+	unmap_sysmem(virt_shared_buf);
+	return efi_ret;
+#else
+	log_err("EFI: Please enable CONFIG_ARM_FFA_TRANSPORT for MM comms\n");
+	return EFI_UNSUPPORTED;
+#endif
+}
+
+/**
+ * select_mm_comms() - detect the available MM transport
+ *
+ * If FF-A is compiled in, make sure the FF-A bus is probed successfully
+ * which means FF-A communication with secure world works and ready
+ * to be used.
+ *
+ * If FF-A is not detected, check if OPTEE support is compiled in.
+ *
+ * Return:
+ *
+ * On success MM_COMMS_FFA or MM_COMMS_OPTEE. Otherwise, MM_COMMS_UNDEFINED
+ */
+static enum mm_comms_select select_mm_comms(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) {
+		ret = uclass_first_device_err(UCLASS_FFA, &dev);
+		if (ret)
+			log_err("EFI: Cannot find FF-A bus device, cannot select FF-A comms\n");
+		else
+			return MM_COMMS_FFA;
+	}
+
+	if (IS_ENABLED(CONFIG_OPTEE))
+		return MM_COMMS_OPTEE;
+
+	return MM_COMMS_UNDEFINED;
 }
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 {
 	efi_status_t ret;
+	enum mm_comms_select mm_comms;
 	struct efi_mm_communicate_header *mm_hdr;
 	struct smm_variable_communicate_header *var_hdr;
 
@@ -162,7 +450,16 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+	mm_comms = select_mm_comms();
+	if (mm_comms == MM_COMMS_UNDEFINED) {
+		ret = EFI_UNSUPPORTED;
+	} else {
+		if (mm_comms == MM_COMMS_OPTEE)
+			ret = optee_mm_communicate(comm_buf, dsize);
+		else
+			ret = ffa_mm_communicate(comm_buf, dsize);
+	}
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -258,6 +555,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
 		goto out;
 	}
 	*size = var_payload->size;
+
+	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
+		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
+			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
+				MM_VARIABLE_COMMUNICATE_SIZE;
+	#endif
+
 	/*
 	 * There seems to be a bug in EDK2 miscalculating the boundaries and
 	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
@@ -697,7 +1001,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v11 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                             ` (8 preceding siblings ...)
  2023-04-12  9:42                                                                                           ` [PATCH v11 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-04-12  9:42                                                                                           ` Abdellatif El Khlifi
  2023-04-17 16:02                                                                                           ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
  11 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:42 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong

turn on EFI MM communication

On corstone1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

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>

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

v9: update copyright string

v8:

* drop OP-TEE configs from Corstone-1000 defconfig

v7:

* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
  FFA_SHARED_MM_BUFFER_OFFSET
* update FFA_SHARED_MM_BUFFER_ADDR value

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

 configs/corstone1000_defconfig |  2 ++
 include/configs/corstone1000.h | 15 +++++++++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index 383317fefe..403d7aee2d 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -52,3 +52,5 @@ CONFIG_DM_SERIAL=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760=y
 CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
index 3347c11792..4ef1f05e40 100644
--- a/include/configs/corstone1000.h
+++ b/include/configs/corstone1000.h
@@ -1,9 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * (C) Copyright 2022 ARM Limited
  * (C) Copyright 2022 Linaro
  * Rui Miguel Silva <rui.silva@linaro.org>
- * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  *
  * Configuration for Corstone1000. Parts were derived from other ARM
  * configurations.
@@ -14,6 +16,15 @@
 
 #include <linux/sizes.h>
 
+#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
+
+/*
+ * shared buffer physical address used for communication between
+ * u-boot and the MM SP
+ */
+#define FFA_SHARED_MM_BUFFER_ADDR	0x02000000UL
+#define FFA_SHARED_MM_BUFFER_OFFSET	0
+
 #define V2M_BASE		0x80000000
 
 #define CFG_PL011_CLOCK	50000000
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 05/10] arm_ffa: introduce armffa command
  2023-04-02  2:40                                                                                           ` Simon Glass
@ 2023-04-12  9:48                                                                                             ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:48 UTC (permalink / raw)
  To: Simon Glass; +Cc: nd, u-boot

On Sun, Apr 02, 2023 at 02:40:34PM +1200, Simon Glass wrote:
> Hi Abdellatif,
> 
> On Wed, 29 Mar 2023 at 05:12, Abdellatif El Khlifi <
> abdellatif.elkhlifi@arm.com> wrote:
> >
> > Provide armffa command showcasing the use of the U-Boot FF-A support
> >
> > armffa is a command showcasing how to invoke FF-A operations.
> > This provides a guidance to the client developers on how to
> > call the FF-A bus interfaces. The command also allows to gather secure
> > partitions information and ping these  partitions. The command is also
> > helpful in testing the communication with secure partitions.
> >
> > For more details please refer to the command documentation [1].
> >
> > [1]: doc/usage/cmd/armffa.rst
> >
> > 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>
> > Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
> >
> > ---
> > Changelog:
> > ===============
> >
> > v10:
> >
> > * use the FF-A driver Uclass operations
> > * use uclass_first_device()
> > * address nits
> >
> > v9:
> >
> > * remove manual FF-A discovery and use DM
> > * use DM class APIs to probe and interact with the FF-A bus
> > * add doc/usage/cmd/armffa.rst
> >
> > v8:
> >
> > * update partition_info_get() second argument to be an SP count
> > * pass NULL device pointer to the FF-A bus discovery and operations
> >
> > v7:
> >
> > * adapt do_ffa_dev_list() following the recent update on
> >   uclass_first_device/uclass_next_device functions (they return void now)
> > * set armffa command to use 64-bit direct messaging
> >
> > v4:
> >
> > * remove pattern data in do_ffa_msg_send_direct_req
> >
> > v3:
> >
> > * use the new driver interfaces (partition_info_get, sync_send_receive)
> >   in armffa command
> >
> > v2:
> >
> > * replace use of ffa_helper_init_device function by
> >  ffa_helper_bus_discover
> >
> > v1:
> >
> > * introduce armffa command
> >
> >  MAINTAINERS                      |   2 +
> >  cmd/Kconfig                      |  10 ++
> >  cmd/Makefile                     |   2 +
> >  cmd/armffa.c                     | 238 +++++++++++++++++++++++++++++++
> >  doc/arch/arm64.ffa.rst           |   7 +
> >  doc/usage/cmd/armffa.rst         | 107 ++++++++++++++
> >  doc/usage/index.rst              |   1 +
> >  drivers/firmware/arm-ffa/Kconfig |   1 +
> >  8 files changed, 368 insertions(+)
> >  create mode 100644 cmd/armffa.c
> >  create mode 100644 doc/usage/cmd/armffa.rst
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 62c30184bb..add208e4ef 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -269,7 +269,9 @@ F:  configs/cortina_presidio-asic-pnand_defconfig
> >  ARM FF-A
> >  M:     Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >  S:     Maintained
> > +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
> > diff --git a/cmd/Kconfig b/cmd/Kconfig
> > index ba5ec69293..b814a20d8a 100644
> > --- a/cmd/Kconfig
> > +++ b/cmd/Kconfig
> > @@ -934,6 +934,16 @@ endmenu
> >
> >  menu "Device access commands"
> >
> > +config CMD_ARMFFA
> > +       bool "Arm FF-A test command"
> > +       depends on ARM_FFA_TRANSPORT
> > +       help
> > +         Provides a test command for the FF-A support
> > +         supported options:
> > +               - Listing the partition(s) info
> > +               - Sending a data pattern to the specified partition
> > +               - Displaying the arm_ffa device info
> > +
> >  config CMD_ARMFLASH
> >         #depends on FLASH_CFI_DRIVER
> >         bool "armflash"
> > diff --git a/cmd/Makefile b/cmd/Makefile
> > index d95833b2de..a1eb45f881 100644
> > --- a/cmd/Makefile
> > +++ b/cmd/Makefile
> > @@ -12,6 +12,8 @@ obj-y += panic.o
> >  obj-y += version.o
> >
> >  # command
> > +
> > +obj-$(CONFIG_CMD_ARMFFA) += armffa.o
> >  obj-$(CONFIG_CMD_ACPI) += acpi.o
> >  obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
> >  obj-$(CONFIG_CMD_AES) += aes.o
> > diff --git a/cmd/armffa.c b/cmd/armffa.c
> > new file mode 100644
> > index 0000000000..d983a23bbc
> > --- /dev/null
> > +++ b/cmd/armffa.c
> > @@ -0,0 +1,238 @@
> > +// 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 <command.h>
> > +#include <dm.h>
> > +#include <mapmem.h>
> > +#include <stdlib.h>
> > +#include <asm/io.h>
> > +
> > +/**
> > + * do_ffa_getpart() - implementation of the getpart subcommand
> > + * @cmdtp:             Command Table
> > + * @flag:              flags
> > + * @argc:              number of arguments
> > + * @argv:              arguments
> > + *
> > + * This function queries the secure partition information which the UUID
> is provided
> 
> s/This function queries/Query/
> 
> We know it is a function so try to be brief and use the imperative mood
> like you do in commit messages.
> 
> > + * as an argument. The function uses the arm_ffa driver
> partition_info_get operation
> > + * which implements FFA_PARTITION_INFO_GET ABI to retrieve the data.
> > + * The input UUID string is expected to be in big endian format.
> > + *
> > + * Return:
> > + *
> > + * CMD_RET_SUCCESS: on success, otherwise failure
> > + */
> > +static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
> char *const argv[])
> > +{
> > +       u32 count = 0;
> > +       int ret;
> > +       struct ffa_partition_info *parts_info;
> > +       u32 info_idx;
> > +       struct udevice *dev = NULL;
> > +
> > +       if (argc != 1)
> > +               return -EINVAL;
> 
> Since this is a command handler, you must return CMD_RET_USAGE here. Please
> fix globally.
> 
> 
> > +
> > +       uclass_first_device(UCLASS_FFA, &dev);
> > +       if (!dev) {
> 
> ret = uclass_first_device_err(...)
> if (ret) {
> 
> (please fix globally)
> 
> > +               log_err("[FFA][CMD] Cannot find FF-A bus device\n");
> > +               return -ENODEV;
> 
> CMD_RET_FAILURE - please fix throughout. Often it is easier to put all this
> code (after arg checking) in a separate function which returns an error
> code, then have the do_... function check that and either return 0 or print
> a message and return CMD_RET_FAILURE.
> 
> > +       }
> > +
> > +       /* Mode 1: getting the number of secure partitions */
> > +       ret = ffa_partition_info_get(dev, argv[0], &count, NULL);
> > +       if (ret) {
> > +               log_err("[FFA][CMD] Failure in querying partitions count
> (error code: %d)\n", ret);
> 
> %dE gives you a nice error name if you want it.
> 
> Do you think you need the [FFA][CMD] stuff? Just the message should be
> enough.
> 
> > +               return ret;
> > +       }
> > +
> > +       if (!count) {
> > +               log_info("[FFA][CMD] No secure partition found\n");
> > +               return ret;
> > +       }
> > +
> > +       /*
> > +        * Pre-allocate a buffer to be filled by the driver
> > +        * with ffa_partition_info structs
> > +        */
> > +
> > +       log_info("[FFA][CMD] Pre-allocating %d partition(s) info
> structures\n", count);
> > +
> > +       parts_info = calloc(count, sizeof(struct ffa_partition_info));
> 
> Just use a local variable and avoid the allocation.

The number of partitions can't be known in advance. A dynamic allocation is needed in this case

> 
> > +       if (!parts_info)
> > +               return -EINVAL;
> > +
> > +       /* Ask the driver to fill the buffer with the SPs info */
> > +
> > +       ret = ffa_partition_info_get(dev, argv[0], &count, parts_info);
> > +       if (ret) {
> > +               log_err("[FFA][CMD] Failure in querying partition(s) info
> (error code: %d)\n", ret);
> > +               free(parts_info);
> > +               return ret;
> > +       }
> > +
> > +       /* SPs found , show the partition information */
> > +       for (info_idx = 0; info_idx < count ; info_idx++) {
> 
> We generally use 'i' for loops as it is shorter.
> 
> > +               log_info("[FFA][CMD] Partition: id = 0x%x , exec_ctxt
> 0x%x , properties 0x%x\n",
> 
> You don't need the 0x. Generally hex is used for everything in U-Boot. If
> you feel there is ambiguity, use %#x
> 
> > +                        parts_info[info_idx].id,
> > +                        parts_info[info_idx].exec_ctxt,
> > +                        parts_info[info_idx].properties);
> > +       }
> > +
> > +       free(parts_info);
> > +
> > +       return 0;
> > +}
> > +
> > +/**
> > + * do_ffa_ping() - implementation of the ping subcommand
> > + * @cmdtp:             Command Table
> > + * @flag:              flags
> > + * @argc:              number of arguments
> > + * @argv:              arguments
> > + *
> > + * This function sends data to the secure partition which the ID is
> provided
> 
> partition for which ?

The secure partition (aka SP) resides in the secure world and is discovered at runtime.
The purpose of the partition is providing secure services (e.g: firmware update, reading EFI variables, ...)

Cheers,
Abdellatif

> 
> > + * as an argument. The function uses the arm_ffa driver
> sync_send_receive operation
> > + * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive
> data.
> > + *
> > + * Return:
> > + *
> > + * CMD_RET_SUCCESS: on success, otherwise failure
> > + */
> > +int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const
> argv[])
> > +{
> > +       struct ffa_send_direct_data msg = {
> > +                       .data0 = 0xaaaaaaaa,
> > +                       .data1 = 0xbbbbbbbb,
> > +                       .data2 = 0xcccccccc,
> > +                       .data3 = 0xdddddddd,
> > +                       .data4 = 0xeeeeeeee,
> > +       };
> > +       u16 part_id;
> > +       int ret;
> > +       struct udevice *dev = NULL;
> > +
> > +       if (argc != 1)
> > +               return -EINVAL;
> > +
> > +       errno = 0;
> > +       part_id = strtoul(argv[0], NULL, 16);
> > +
> > +       if (errno) {
> > +               log_err("[FFA][CMD] Invalid partition ID\n");
> > +               return -EINVAL;
> > +       }
> > +
> > +       uclass_first_device(UCLASS_FFA, &dev);
> > +       if (!dev) {
> > +               log_err("[FFA][CMD] Cannot find FF-A bus device\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
> > +       if (!ret) {
> > +               u8 cnt;
> > +
> > +               log_info("[FFA][CMD] SP response:\n[LSB]\n");
> > +               for (cnt = 0;
> > +                    cnt < sizeof(struct ffa_send_direct_data) /
> sizeof(u64);
> > +                    cnt++)
> > +                       log_info("[FFA][CMD] 0x%llx\n", ((u64
> *)&msg)[cnt]);
> > +       } else {
> > +               log_err("[FFA][CMD] Sending direct request error (%d)\n",
> ret);
> > +       }
> > +
> > +       return ret;
> > +}
> > +
> > +/**
> > + *do_ffa_devlist() - implementation of the devlist subcommand
> > + * @cmdtp: [in]                Command Table
> > + * @flag:              flags
> > + * @argc:              number of arguments
> > + * @argv:              arguments
> > + *
> > + * This function queries the device belonging to the UCLASS_FFA
> > + * class.
> > + *
> > + * Return:
> > + *
> > + * CMD_RET_SUCCESS: on success, otherwise failure
> > + */
> > +int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char
> *const argv[])
> > +{
> > +       struct udevice *dev = NULL;
> > +
> > +       uclass_first_device(UCLASS_FFA, &dev);
> > +       if (!dev) {
> > +               log_err("[FFA][CMD] Cannot find FF-A bus device\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       log_info("[FFA][CMD] device name %s, dev %08x, driver name %s,
> ops %08x\n",
> > +                dev->name,
> > +                (u32)map_to_sysmem(dev),
> 
> use %p as this is a pointer
> 
> > +                dev->driver->name,
> > +                (u32)map_to_sysmem(dev->driver->ops));
> 
> Use %p as this is a pointer
> 
> > +
> > +       return 0;
> > +}
> > +
> > +static struct cmd_tbl armffa_commands[] = {
> > +       U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_getpart, "", ""),
> > +       U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_ping, "", ""),
> > +       U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_devlist, "", ""),
> > +};
> > +
> > +/**
> > + * do_armffa() - the armffa command main function
> > + * @cmdtp:     Command Table
> > + * @flag:              flags
> > + * @argc:              number of arguments
> > + * @argv:              arguments
> > + *
> > + * This function identifies which armffa subcommand to run.
> > + * Then, it makes sure the arm_ffa device is probed and
> > + * ready for use.
> > + * Then, it runs the subcommand.
> > + *
> > + * Return:
> > + *
> > + * CMD_RET_SUCCESS: on success, otherwise failure
> > + */
> > +static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char
> *const argv[])
> 
> You can use U_BOOT_CMD_WITH_SUBCMDS and drop this function
> 
> > +{
> > +       struct cmd_tbl *armffa_cmd;
> > +       int ret;
> > +
> > +       if (argc < 2)
> > +               return CMD_RET_USAGE;
> > +
> > +       armffa_cmd = find_cmd_tbl(argv[1], armffa_commands,
> ARRAY_SIZE(armffa_commands));
> > +
> > +       argc -= 2;
> > +       argv += 2;
> > +
> > +       if (!armffa_cmd || argc > armffa_cmd->maxargs)
> > +               return CMD_RET_USAGE;
> > +
> > +       ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
> > +
> > +       return cmd_process_error(armffa_cmd, ret);
> > +}
> > +
> > +U_BOOT_CMD(armffa, 4, 1, do_armffa,
> > +          "Arm FF-A operations test command",
> > +          "getpart <partition UUID>\n"
> > +          "     - lists the partition(s) info\n"
> > +          "ping <partition ID>\n"
> > +          "     - sends a data pattern to the specified partition\n"
> > +          "devlist\n"
> > +          "     - displays information about the FF-A device/driver\n");
> > diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> > index ddf6435402..5fedb0c255 100644
> > --- a/doc/arch/arm64.ffa.rst
> > +++ b/doc/arch/arm64.ffa.rst
> > @@ -218,6 +218,13 @@ The following features are provided:
> >
> >  - FF-A bus can be compiled and used without EFI
> >
> > +The armffa command
> > +-----------------------------------
> > +
> > +armffa is an implementation defined command showcasing how to use the
> FF-A bus and how to invoke the driver operations.
> > +
> > +Please refer the command documentation at doc/usage/cmd/armffa.rst
> > +
> >  Example of boot logs with FF-A enabled
> >  --------------------------------------
> >
> > diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
> > new file mode 100644
> > index 0000000000..9bf59e393b
> > --- /dev/null
> > +++ b/doc/usage/cmd/armffa.rst
> > @@ -0,0 +1,107 @@
> > +.. SPDX-License-Identifier: GPL-2.0+:
> > +
> > +armffa command
> > +==============
> > +
> > +Synopsis
> > +--------
> > +
> > +::
> > +
> > +   armffa [sub-command] [arguments]
> > +
> > +   sub-commands:
> > +
> > +        getpart [partition UUID]
> > +
> > +            lists the partition(s) info
> > +
> > +        ping [partition ID]
> > +
> > +            sends a data pattern to the specified partition
> > +
> > +        devlist
> > +
> > +            displays information about the FF-A device/driver
> > +
> > +Description
> > +-----------
> > +
> > +armffa is a command showcasing how to use the FF-A bus and how to invoke
> its operations.
> > +
> > +This provides a guidance to the client developers on how to call the
> FF-A bus interfaces.
> > +
> > +The command also allows to gather secure partitions information and ping
> these  partitions.
> > +
> > +The command is also helpful in testing the communication with secure
> partitions.
> > +
> > +Example
> > +-------
> > +
> > +The following examples are run on Corstone-1000 platform with debug logs
> enabled.
> > +
> > +* ping
> > +
> > +::
> > +
> > +   corstone1000# armffa ping 0x8003
> > +   [FFA][CMD] SP response:
> > +   [LSB]
> > +   [FFA][CMD] 0xfffffffe
> > +   [FFA][CMD] 0x0
> > +   [FFA][CMD] 0x0
> > +   [FFA][CMD] 0x0
> > +   [FFA][CMD] 0x0
> > +
> > +* ping (failure case)
> > +
> > +::
> > +
> > +   corstone1000# armffa ping 0x8009
> > +   [FFA][CMD] Sending direct request error (-22)
> > +   Command 'ping' failed: Error -22
> > +
> > +* getpart
> > +
> > +::
> > +
> > +   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
> > +   [FFA] Preparing for checking partitions count
> > +   [FFA] Searching partitions using the provided UUID
> > +   [FFA] No partition found. Querying framework ...
> > +   [FFA] Reading partitions data from the RX buffer
> > +   [FFA] Number of partition(s) matching the UUID: 1
> > +   [FFA][CMD] Pre-allocating 1 partition(s) info structures
> > +   [FFA] Preparing for filling partitions info
> > +   [FFA] Searching partitions using the provided UUID
> > +   [FFA] Partition ID 8003 matches the provided UUID
> > +   [FFA][CMD] Partition: id = 0x8003 , exec_ctxt 0x1 , properties 0x3
> 
> To me this [FFA] stuff is redundant and it looks awful. Please drop it.
> 
> > +
> > +* getpart (failure case)
> > +
> > +::
> > +
> > +   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7228
> > +   [FFA] Preparing for checking partitions count
> > +   [FFA] Searching partitions using the provided UUID
> > +   [FFA] No partition found. Querying framework ...
> > +   [FFA] INVALID_PARAMETERS: Unrecognized UUID
> > +   [FFA][CMD] Failure in querying partitions count (error code: -22)
> > +   Command 'getpart' failed: Error -22
> > +
> > +* devlist
> > +
> > +::
> > +
> > +   corstone1000# armffa devlist
> > +   [FFA][CMD] device name arm_ffa, dev fdf41c30, driver name arm_ffa,
> ops fffc0fc8
> > +
> > +Configuration
> > +-------------
> > +
> > +The command is available if CONFIG_CMD_ARMFFA=y and
> CONFIG_ARM_FFA_TRANSPORT=y.
> > +
> > +Return value
> > +------------
> > +
> > +The return value $? is 0 (true) on success and a negative error code on
> failure.
> > diff --git a/doc/usage/index.rst b/doc/usage/index.rst
> > index bc85e1d49a..df107fb710 100644
> > --- a/doc/usage/index.rst
> > +++ b/doc/usage/index.rst
> > @@ -21,6 +21,7 @@ Shell commands
> >
> >     cmd/acpi
> >     cmd/addrmap
> > +   cmd/armffa
> >     cmd/askenv
> >     cmd/base
> >     cmd/bdinfo
> > diff --git a/drivers/firmware/arm-ffa/Kconfig
> b/drivers/firmware/arm-ffa/Kconfig
> > index 9200c8028b..a7d5392859 100644
> > --- a/drivers/firmware/arm-ffa/Kconfig
> > +++ b/drivers/firmware/arm-ffa/Kconfig
> > @@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
> >         depends on DM && ARM64
> >         select ARM_SMCCC
> >         select ARM_SMCCC_FEATURES
> > +       imply CMD_ARMFFA
> >         select LIB_UUID
> >         select DEVRES
> >         help
> > --
> > 2.25.1
> >
> 
> Regards,
> SImon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 06/10] arm_ffa: introduce sandbox FF-A support
  2023-04-02  2:41                                                                                           ` Simon Glass
@ 2023-04-12  9:52                                                                                             ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:52 UTC (permalink / raw)
  To: Simon Glass; +Cc: nd, u-boot

On Sun, Apr 02, 2023 at 02:41:01PM +1200, Simon Glass wrote:
> Hi Abdellatif,
> 
> On Wed, 29 Mar 2023 at 05:12, Abdellatif El Khlifi <
> abdellatif.elkhlifi@arm.com> wrote:
> >
> > 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>
> > 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>
> > Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
> >
> > ---
> > Changelog:
> > ===============
> >
> > v10:
> >
> > * split the FF-A sandbox support into an emulator and a driver
> > * read FFA_VERSION and FFA_PARTITION_INFO_GET state using
> >    sandbox_ffa_query_core_state()
> > * drop CONFIG_SANDBOX_FFA config
> > * address nits
> >
> > v9: align FF-A sandbox driver with FF-A discovery through DM
> >
> > v8: update ffa_bus_prvdata_get() to return a pointer rather than
> >     a pointer address
> >
> > v7: state that sandbox driver supports only 64-bit direct messaging
> >
> > v4: align sandbox driver with the new FF-A driver interfaces
> >     and new way of error handling
> >
> > v1: introduce the sandbox driver
> >
> >  MAINTAINERS                                   |   3 +-
> >  arch/sandbox/dts/sandbox.dtsi                 |   8 +
> >  arch/sandbox/dts/test.dts                     |   8 +
> >  arch/sandbox/include/asm/sandbox_arm_ffa.h    |  68 ++
> >  .../include/asm/sandbox_arm_ffa_priv.h        | 133 ++++
> >  configs/sandbox64_defconfig                   |   1 +
> >  configs/sandbox_defconfig                     |   1 +
> >  doc/arch/arm64.ffa.rst                        |   7 +-
> >  doc/arch/sandbox/sandbox.rst                  |   1 +
> >  drivers/firmware/arm-ffa/Kconfig              |  13 +-
> >  drivers/firmware/arm-ffa/Makefile             |  10 +-
> >  drivers/firmware/arm-ffa/ffa-emul-uclass.c    | 732 ++++++++++++++++++
> >  .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |  14 -
> >  drivers/firmware/arm-ffa/sandbox_ffa.c        | 108 +++
> >  include/dm/uclass-id.h                        |   1 +
> >  15 files changed, 1087 insertions(+), 21 deletions(-)
> >  create mode 100644 arch/sandbox/include/asm/sandbox_arm_ffa.h
> >  create mode 100644 arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
> >  create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
> >  delete mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> >  create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
> >
> 
> [..]
> 
> > +/**
> > + * sandbox_ffa_get_fwk_version() - Return the FFA framework version
> > + * @dev: The sandbox FF-A emulator device
> > + * @func_data:  Pointer to the FF-A function arguments container
> structure
> > + *
> > + * Return the FFA framework version read from the FF-A emulator data.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int sandbox_ffa_get_fwk_version(struct udevice *dev, struct
> ffa_sandbox_data *func_data)
> > +{
> > +       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
> > +
> > +       if (!func_data)
> > +               return -EINVAL;
> > +
> > +       if (!func_data->data0 ||
> > +           func_data->data0_size != sizeof(priv->fwk_version))
> > +               return -EINVAL;
> > +
> > +       *((u32 *)func_data->data0) = priv->fwk_version;
> > +
> > +       return 0;
> > +}
> > +
> > +/**
> > + * sandbox_ffa_get_parts() - Return the address of partitions data
> > + * @dev: The sandbox FF-A emulator device
> > + * @func_data:  Pointer to the FF-A function arguments container
> structure
> > + *
> > + * Return the address of partitions data read from the FF-A emulator
> data.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int sandbox_ffa_get_parts(struct udevice *dev, struct
> ffa_sandbox_data *func_data)
> > +{
> > +       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
> > +
> > +       if (!func_data)
> > +               return -EINVAL;
> > +
> > +       if (!func_data->data0 ||
> > +           func_data->data0_size != sizeof(struct ffa_partitions *))
> > +               return -EINVAL;
> > +
> > +       *((struct ffa_partitions **)func_data->data0) = &priv->partitions;
> > +
> > +       return 0;
> > +}
> > +
> > +/**
> > + * sandbox_ffa_query_core_state() - Inspect the FF-A ABIs
> > + * @queried_func_id:   The FF-A function to be queried
> > + * @func_data:  Pointer to the FF-A function arguments container
> structure
> > + *
> > + * Queries the status of FF-A ABI specified in the input argument.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int sandbox_ffa_query_core_state(u32 queried_func_id,
> > +                                struct ffa_sandbox_data *func_data)
> > +{
> > +       struct udevice *dev;
> 
> Please can you use 'emul' for the emulator so it is separate from the
> device?
> 
> > +
> > +       uclass_first_device(UCLASS_FFA_EMUL, &dev);
> > +       if (!dev) {
> > +               log_err("[FFA][SANDBOX][Emul] Cannot find FF-A emulator
> during querying state\n");
> > +               return -ENODEV;
> > +       }
> 
> How about storing the emulator somewhere? You could have:
> 
> struct sandbox_ffa_priv {
>    struct udevice *emul;
> };
> 
> .priv = sizeof(sandbox_ffa_priv)
>

in patchset v11 the sandbox emulator pointer is stored in the FF-A device uc_priv (struct ffa_priv)

Cheers,
Abdellatif

> > +
> > +       switch (queried_func_id) {
> > +       case FFA_RXTX_MAP:
> > +       case FFA_RXTX_UNMAP:
> > +       case FFA_RX_RELEASE:
> > +               return sandbox_ffa_get_rxbuf_flags(dev, queried_func_id,
> func_data);
> > +       case FFA_VERSION:
> > +               return sandbox_ffa_get_fwk_version(dev, func_data);
> > +       case FFA_PARTITION_INFO_GET:
> > +               return sandbox_ffa_get_parts(dev, func_data);
> > +       default:
> > +               log_err("[FFA][Sandbox][Emul] Undefined FF-A interface
> (%d)\n",
> > +                       queried_func_id);
> > +               return -EINVAL;
> > +       }
> > +}
> > +
> > +/**
> > + * sandbox_arm_ffa_smccc_smc() - FF-A SMC call emulation
> > + * @args:      the SMC call arguments
> > + * @res:       the SMC call returned data
> > + *
> > + * Emulates the FF-A ABIs SMC call.
> > + * The emulated FF-A ABI is identified and invoked.
> > + * FF-A emulation is based on the FF-A specification 1.0
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure.
> > + * FF-A protocol error codes are returned using the registers arguments
> as
> > + * described by the specification
> > + */
> > +void sandbox_arm_ffa_smccc_smc(ffa_value_t args, ffa_value_t *res)
> > +{
> > +       int ret = 0;
> > +       struct udevice *dev;
> > +
> > +       uclass_first_device(UCLASS_FFA_EMUL, &dev);
> > +       if (!dev) {
> > +               log_err("[FFA][SANDBOX][Emul] Cannot find FF-A emulator
> during SMC emulation\n");
> > +               return;
> > +       }
> > +
> > +       switch (args.a0) {
> > +       case FFA_SMC_32(FFA_VERSION):
> > +               ret = sandbox_ffa_version(dev, &args, res);
> > +               break;
> > +       case FFA_SMC_32(FFA_PARTITION_INFO_GET):
> > +               ret = sandbox_ffa_partition_info_get(dev, &args, res);
> > +               break;
> > +       case FFA_SMC_32(FFA_RXTX_UNMAP):
> > +               ret = sandbox_ffa_rxtx_unmap(dev, &args, res);
> > +               break;
> > +       case FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ):
> > +               ret = sandbox_ffa_msg_send_direct_req(dev, &args, res);
> > +               break;
> > +       case FFA_SMC_32(FFA_ID_GET):
> > +               ret = sandbox_ffa_id_get(dev, &args, res);
> > +               break;
> > +       case FFA_SMC_32(FFA_FEATURES):
> > +               ret = sandbox_ffa_features(&args, res);
> > +               break;
> > +       case FFA_SMC_64(FFA_RXTX_MAP):
> > +               ret = sandbox_ffa_rxtx_map(dev, &args, res);
> > +               break;
> > +       case FFA_SMC_32(FFA_RX_RELEASE):
> > +               ret = sandbox_ffa_rx_release(dev, &args, res);
> > +               break;
> > +       default:
> > +               log_err("[FFA][Sandbox][Emul] Undefined FF-A interface
> (0x%lx)\n",
> > +                       args.a0);
> > +       }
> > +
> > +       if (ret != 0)
> > +               log_err("[FFA][Sandbox][Emul] FF-A ABI internal failure
> (%d)\n", ret);
> > +}
> > +
> > +/**
> > + * ffa_emul_find() - Finds the FF-A emulator
> > + * @dev:       the sandbox FF-A device (sandbox-arm-ffa)
> > + * @emulp:     the FF-A emulator device (sandbox-ffa-emul)
> > + *
> > + * Searches for the FF-A emulator and returns its device pointer.
> > + *
> > + * Return:
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_emul_find(struct udevice *dev, struct udevice **emulp)
> > +{
> > +       if (!emulp)
> > +               return -EINVAL;
> > +
> > +       *emulp = NULL;
> > +
> > +       uclass_first_device(UCLASS_FFA_EMUL, emulp);
> > +       if (!(*emulp)) {
> > +               log_err("[FFA][SANDBOX][Emul] Cannot find FF-A
> emulator\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       log_info("[FFA][Sandbox][Emul] FF-A emulator found\n");
> > +
> > +       return 0;
> > +}
> > +
> > +UCLASS_DRIVER(ffa_emul) = {
> > +       .name           = "ffa_emul",
> > +       .id             = UCLASS_FFA_EMUL,
> > +};
> > +
> > +/* Sandbox Arm FF-A emulator operations */
> > +
> > +static const struct ffa_emul_ops sandbox_ffa_emul_ops = {
> > +       .invoke_ffa_fn = sandbox_arm_ffa_smccc_smc,
> > +};
> > +
> > +static const struct udevice_id sandbox_ffa_emul_ids[] = {
> > +       { .compatible = "sandbox,arm-ffa-emul" },
> > +       { }
> > +};
> > +
> > +/* Declaring the sandbox FF-A emulator under UCLASS_FFA_EMUL */
> > +U_BOOT_DRIVER(sandbox_ffa_emul) = {
> > +       .name           = "sandbox_ffa_emul",
> > +       .id             = UCLASS_FFA_EMUL,
> > +       .of_match       = sandbox_ffa_emul_ids,
> > +       .ops            = &sandbox_ffa_emul_ops,
> > +       .priv_auto      = sizeof(struct sandbox_ffa_emul),
> > +};
> > diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> > deleted file mode 100644
> > index 4338f9c9b1..0000000000
> > --- a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> > +++ /dev/null
> > @@ -1,14 +0,0 @@
> > -/* SPDX-License-Identifier: GPL-2.0+ */
> > -/*
> > - * Copyright 2022-2023 Arm Limited and/or its affiliates <
> open-source-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..bb150fd5cd
> > --- /dev/null
> > +++ b/drivers/firmware/arm-ffa/sandbox_ffa.c
> > @@ -0,0 +1,108 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright 2022-2023 Arm Limited and/or its affiliates <
> open-source-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;
> > +
> > +/**
> > + * ffa_set_smc_conduit() - Set the SMC conduit
> > + *
> > + * Selects the SMC conduit by setting the FF-A ABI invoke function.
> > + * The function emulating the SMC call is provided by the FF-A emulator.
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_set_smc_conduit(void)
> > +{
> > +       struct udevice *emul;
> > +       int ret;
> > +
> > +       ret = ffa_emul_find(NULL, &emul);
> > +       if (ret) {
> > +               log_err("[FFA][Sandbox] Cannot find FF-A emulator, SMC
> emulation failure\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       if (!ffa_emul_get_ops(emul)->invoke_ffa_fn) {
> > +               log_err("[FFA][Sandbox] Cannot get FF-A emulator ops, SMC
> emulation failure\n");
> > +               return -ENOSYS;
> > +       }
> > +
> > +       dscvry_info.invoke_ffa_fn = ffa_emul_get_ops(emul)->invoke_ffa_fn;
> > +       log_info("[FFA][Sandbox] Using emulated Arm SMC for FF-A
> conduit\n");
> > +
> > +       return 0;
> > +}
> > +
> > +/**
> > + * sandbox_ffa_probe() - The sandbox FF-A driver probe function
> > + * @dev:       the sandbox Arm FF-A bus device (sandbox-arm-ffa)
> > + *
> > + * Probing is done through ffa_do_probe()
> > + *
> > + * Return:
> > + *
> > + * 0 on success. Otherwise, failure
> > + */
> > +static int sandbox_ffa_probe(struct udevice *dev)
> > +{
> > +       return ffa_do_probe(dev);
> 
> Move to a uclass pre_probe()  method.
> 
> > +}
> 
> Drop this. You can add it in the uclass as a child_pre_probe member.
> 
> > +
> > +/**
> > + * sandbox_ffa_bind() - The sandbox FF-A driver bind function
> > + * @dev:       the sandbox-arm-ffa device
> > + * Tries to discover the emulated FF-A bus.
> > + * Return:
> > + *
> > + * 0 on success.
> > + */
> > +static int sandbox_ffa_bind(struct udevice *dev)
> > +{
> > +       bool ret;
> > +
> > +       log_info("[FFA][Sandbox] binding the device\n");
> > +
> > +       ret = ffa_try_discovery();
> 
> The code for this is immediately above. Just do that here, or make the
> above function static and rename it.
> 
> > +       if (ret)
> > +               return 0;
> > +       else
> > +               return -ENODEV;
> 
> 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,
> > +       .probe          = sandbox_ffa_probe,
> > +       .bind           = sandbox_ffa_bind,
> > +       .ops            = &sandbox_ffa_ops,
> > +};
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index df77c7da58..4658411935 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -61,6 +61,7 @@ enum uclass_id {
> >         UCLASS_ETH,             /* Ethernet device */
> >         UCLASS_ETH_PHY,         /* Ethernet PHY device */
> >         UCLASS_FFA,             /* Arm Firmware Framework for Armv8-A */
> > +       UCLASS_FFA_EMUL,                /* sandbox FF-A device emulator */
> >         UCLASS_FIRMWARE,        /* Firmware */
> >         UCLASS_FPGA,            /* FPGA device */
> >         UCLASS_FUZZING_ENGINE,  /* Fuzzing engine */
> > --
> > 2.25.1
> >
> 
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v10 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-03-31  8:29                                                                                           ` Ilias Apalodimas
@ 2023-04-12  9:59                                                                                             ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12  9:59 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: nd, u-boot

On Fri, Mar 31, 2023 at 11:29:26AM +0300, Ilias Apalodimas wrote:
> Hi Abdellatif,
> 
> On Tue, Mar 28, 2023 at 05:11:56PM +0100, Abdellatif El Khlifi wrote:
> > Add MM communication support using FF-A transport
> >
> > This feature allows accessing MM partitions services through
> > EFI MM communication protocol. MM partitions such as StandAlonneMM
> > or smm-gateway secure partitions which reside in secure world.
> >
> > An MM shared buffer and a door bell event are used to exchange
> > the data.
> >
> > The data is used by EFI services such as GetVariable()/SetVariable()
> > and copied from the communication buffer to the MM shared buffer.
> >
> > The secure partition is notified about availability of data in the
> > MM shared buffer by an FF-A message (door bell).
> >
> > On such event, MM SP can read the data and updates the MM shared
> > buffer with the response data.
> >
> > The response data is copied back to the communication buffer and
> > consumed by the EFI subsystem.
> >
> > MM communication protocol supports FF-A 64-bit direct messaging.
> >
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>
> >
> > ---
> > Changelog:
> > ===============
> >
> > v10:
> >
> > * use the FF-A driver Uclass operations
> > * use uclass_first_device()
> > * addressing nits
> >
> > v9: align how FF-A is used with FF-A discovery through DM
> >
> > v8:
> >
> > * isolate the compilation choices between FF-A and OP-TEE
> > * update partition_info_get() second argument to be an SP count
> > * pass NULL device pointer to the FF-A bus discovery and operations
> >
> > v7:
> >
> > * set the MM door bell event to use 64-bit direct messaging
> > * issue a compile time error when one of these macros are not found :
> >   FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
> > * make mm_sp_svc_uuid static
> > * replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
> > * improve use of unmap_sysmem() in ffa_mm_communicate()
> >
> > v6:
> >
> > * add FF-A runtime discovery at MM communication level
> > * drop EFI runtime support for FF-A MM communication
> > * revert the changes in include/mm_communication.h for
> >   efi_mm_communicate_header and smm_variable_access structures
> >
> > v4:
> >
> > * use the new FF-A driver interfaces
> > * discover MM partitions at runtime
> > * copy FF-A driver private data to EFI runtime section at
> >   ExitBootServices()
> > * drop use of FFA_ERR_STAT_SUCCESS error code
> > * replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
> >   in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
> > * revert the error log in mm_communicate() in case of failure
> > * remove packed attribute from efi_mm_communicate_header and
> >   smm_variable_communicate_header
> >
> > v2:
> >
> > * set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings
> >
> > v1:
> >
> > * introduce FF-A MM communication
> >
> >  include/mm_communication.h        |   6 +
> >  lib/efi_loader/Kconfig            |  14 +-
> >  lib/efi_loader/efi_variable_tee.c | 300 +++++++++++++++++++++++++++++-
> >  3 files changed, 314 insertions(+), 6 deletions(-)
> >
> > diff --git a/include/mm_communication.h b/include/mm_communication.h
> > index e65fbde60d..87509fec3f 100644
> > --- a/include/mm_communication.h
> > +++ b/include/mm_communication.h
> > @@ -6,6 +6,9 @@
> >   *  Copyright (c) 2017, Intel Corporation. All rights reserved.
> >   *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
> >   *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
> > + *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> > + *    Authors:
> > + *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >
> >  #ifndef _MM_COMMUNICATION_H_
> > @@ -13,6 +16,9 @@
> >
> >  #include <part_efi.h>
> >
> > +/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
> > +#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
> > +
> >  /*
> >   * Interface to the pseudo Trusted Application (TA), which provides a
> >   * communication channel with the Standalone MM (Management Mode)
> > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > index c5835e6ef6..08a6b84101 100644
> > --- a/lib/efi_loader/Kconfig
> > +++ b/lib/efi_loader/Kconfig
> > @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
> >  	  stored as file /ubootefi.var on the EFI system partition.
> >
> >  config EFI_MM_COMM_TEE
> > -	bool "UEFI variables storage service via OP-TEE"
> > -	depends on OPTEE
> > +	bool "UEFI variables storage service via the trusted world"
> > +	depends on OPTEE || ARM_FFA_TRANSPORT
> >  	help
> > +	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
> > +	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> > +	  When using the u-boot FF-A  driver any MM SP is supported.
> > +
> >  	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
> >  	  variable related operations to that. The application will verify,
> >  	  authenticate and store the variables on an RPMB.
> >
> > +	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> > +	  operations to the MM SP running in the secure world.
> > +	  A door bell mechanism is used to notify the SP when there is data in the shared
> > +	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
> > +	  the door bell event.
> > +
> >  config EFI_VARIABLE_NO_STORE
> >  	bool "Don't persist non-volatile UEFI variables"
> >  	help
> > diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> > index dfef18435d..a3060b4e7e 100644
> > --- a/lib/efi_loader/efi_variable_tee.c
> > +++ b/lib/efi_loader/efi_variable_tee.c
> > @@ -4,9 +4,14 @@
> >   *
> >   *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
> >   *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
> > + *  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 <efi.h>
> >  #include <efi_api.h>
> >  #include <efi_loader.h>
> > @@ -15,6 +20,36 @@
> >  #include <malloc.h>
> >  #include <mm_communication.h>
> >
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +
> > +#include <arm_ffa.h>
> > +#include <cpu_func.h>
> > +#include <mapmem.h>
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> > +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_SIZE 0
> > +#endif
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_OFFSET
> > +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_OFFSET 0
> > +#endif
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> > +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_ADDR 0
> > +#endif
> > +
> > +/* MM return codes */
> > +#define MM_SUCCESS (0)
> > +
> > +static const char *mm_sp_svc_uuid = MM_SP_UUID;
> > +
> > +static u16 mm_sp_id;
> > +
> > +#endif
> > +
> >  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
> >  static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
> >  static efi_uintn_t max_payload_size;	/* func + data */
> > @@ -24,6 +59,7 @@ struct mm_connection {
> >  	u32 session;
> >  };
> >
> > +#if (IS_ENABLED(CONFIG_OPTEE))
> >  /**
> >   * get_connection() - Retrieve OP-TEE session for a specific UUID.
> >   *
> > @@ -143,13 +179,252 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
> >
> >  	return ret;
> >  }
> > +#endif
> > +
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +
> > +/**
> > + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> > + *
> > + * Notifies the MM partition in the trusted world that
> > + * data is available in the shared buffer.
> > + * This is a blocking call during which trusted world has exclusive access
> > + * to the MM shared buffer.
> > + *
> > + * Return:
> > + *
> > + * 0 on success
> > + */
> > +static int ffa_notify_mm_sp(void)
> > +{
> > +	struct ffa_send_direct_data msg = {0};
> > +	int ret;
> > +	int sp_event_ret = -1;
> > +	struct udevice *dev;
> > +
> > +	uclass_first_device(UCLASS_FFA, &dev);
> > +	if (!dev) {
> > +		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
> > +
> > +	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
> > +	if (ret != 0)
> 
> We usually do if (!ret)
> 
> > +		return ret;
> > +
> > +	sp_event_ret = msg.data0; /* x3 */
> > +
> > +	if (sp_event_ret == MM_SUCCESS)
> > +		return 0;
> > +
> > +	/* Failure to notify the MM SP */
> > +
> > +	return -EACCES;
> > +}
> > +
> > +/**
> > + * ffa_discover_mm_sp_id() - Query the MM partition ID
> > + *
> > + * Use the FF-A driver to get the MM partition ID.
> > + * If multiple partitions are found, use the first one.
> > + * This is a boot time function.
> > + *
> > + * Return:
> > + *
> > + * 0 on success
> > + */
> > +static int ffa_discover_mm_sp_id(void)
> > +{
> > +	u32 count = 0;
> > +	int ret;
> > +	struct ffa_partition_info *parts_info;
> > +	struct udevice *dev;
> > +
> > +	uclass_first_device(UCLASS_FFA, &dev);
> > +	if (!dev) {
> > +		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	/* Get from the driver the count of the SPs matching the UUID */
> > +	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, NULL);
> > +	if (ret != 0) {
> > +		log_err("EFI: Failure in querying SPs count (%d), MM SP discovery failure\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	if (!count) {
> > +		log_info("EFI: No MM partition found\n");
> > +		return ret;
> > +	}
> > +
> > +	/* Pre-allocate a buffer to be filled by the driver with ffa_partition_info structs */
> > +
> > +	log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
> > +
> > +	parts_info = calloc(count, sizeof(*parts_info));
> > +	if (!parts_info)
> > +		return -ENOMEM;
> > +
> > +	/* Ask the driver to fill the buffer with the SPs info */
> > +	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, parts_info);
> > +	if (ret) {
> > +		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
> > +		free(parts_info);
> > +		return ret;
> > +	}
> > +
> > +	/* MM SPs found , use the first one */
> > +
> > +	mm_sp_id = parts_info[0].id;
> > +
> > +	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
> > +
> > +	free(parts_info);
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
> > + * @comm_buf:		locally allocated communication buffer used for rx/tx
> > + * @dsize:				communication buffer size
> > + *
> > + * Issues a door bell event to notify the MM partition (SP) running in OP-TEE
> > + * that there is data to read from the shared buffer.
> > + * Communication with the MM SP is performed using FF-A transport.
> > + * On the event, MM SP can read the data from the buffer and
> > + * update the MM shared buffer with response data.
> > + * The response data is copied back to the communication buffer.
> > + *
> > + * Return:
> > + *
> > + * EFI status code
> > + */
> > +static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
> > +{
> > +	ulong tx_data_size;
> > +	int ffa_ret;
> > +	efi_status_t efi_ret;
> > +	struct efi_mm_communicate_header *mm_hdr;
> > +	void *virt_shared_buf;
> > +
> > +	if (!comm_buf)
> > +		return EFI_INVALID_PARAMETER;
> > +
> > +	/* Discover MM partition ID at boot time */
> > +	if (!mm_sp_id && ffa_discover_mm_sp_id()  != 0) {
> > +		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
> > +		return EFI_UNSUPPORTED;
> > +	}
> > +
> > +	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> > +	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
> > +
> > +	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
> > +		return EFI_INVALID_PARAMETER;
> > +
> > +	/* Copy the data to the shared buffer */
> > +
> > +	virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
> > +	memcpy(virt_shared_buf, comm_buf, tx_data_size);
> > +
> > +	/*
> > +	 * The secure world might have cache disabled for
> > +	 * the device region used for shared buffer (which is the case for Optee).
> > +	 * In this case, the secure world reads the data from DRAM.
> > +	 * Let's flush the cache so the DRAM is updated with the latest data.
> > +	 */
> > +#ifdef CONFIG_ARM64
> > +	invalidate_dcache_all();
> > +#endif
> > +
> > +	/* Announce there is data in the shared buffer */
> > +
> > +	ffa_ret = ffa_notify_mm_sp();
> > +
> > +	switch (ffa_ret) {
> > +	case 0: {
> > +		ulong rx_data_size;
> > +		/* Copy the MM SP response from the shared buffer to the communication buffer */
> > +		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> > +			sizeof(efi_guid_t) +
> > +			sizeof(size_t);
> > +
> > +		if (rx_data_size > comm_buf_size) {
> > +			efi_ret = EFI_OUT_OF_RESOURCES;
> > +			break;
> > +		}
> > +
> > +		memcpy(comm_buf, virt_shared_buf, rx_data_size);
> > +		efi_ret = EFI_SUCCESS;
> > +		break;
> > +	}
> > +	case -EINVAL:
> > +		efi_ret = EFI_DEVICE_ERROR;
> > +		break;
> > +	case -EPERM:
> > +		efi_ret = EFI_INVALID_PARAMETER;
> > +		break;
> > +	case -EACCES:
> > +		efi_ret = EFI_ACCESS_DENIED;
> > +		break;
> > +	case -EBUSY:
> > +		efi_ret = EFI_OUT_OF_RESOURCES;
> > +		break;
> > +	default:
> > +		efi_ret = EFI_ACCESS_DENIED;
> > +	}
> > +
> > +	unmap_sysmem(virt_shared_buf);
> > +	return efi_ret;
> > +}
> > +#endif
> > +
> > +/**
> > + * select_ffa_mm_comms() - checks FF-A support availability
> > + *
> > + * Making sure FF-A is compiled in. If that's the case try to make sure
> > + * the FF-A bus is probed successfully which means FF-A communication
> > + * with secure world works and ready to be used.
> > + *
> > + * Return:
> > + *
> > + * 0: FF-A ready for use. Otherwise, failure
> > + */
> > +static efi_status_t select_ffa_mm_comms(void)
> > +{
> > +	efi_status_t ret = EFI_UNSUPPORTED;
> > +
> > +	if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) {
> > +		struct udevice *dev;
> > +
> > +		uclass_first_device(UCLASS_FFA, &dev);
> > +		if (!dev) {
> > +			log_err("EFI: Cannot find FF-A bus device, cannot select FF-A comms\n");
> > +			ret = EFI_NOT_READY;
> > +		} else {
> > +			ret = EFI_SUCCESS;
> > +		}
> > +	}
> > +
> > +	return ret;
> > +}
> >
> >  /**
> > - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
> > + * mm_communicate() - Adjust the communication buffer to the MM SP and send
> >   * it to OP-TEE
> >   *
> > - * @comm_buf:		locally allocted communcation buffer
> > + * @comm_buf:		locally allocated communication buffer
> >   * @dsize:		buffer size
> > + *
> > + * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
> > + * The comm_buf format is the same for both partitions.
> > + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> > + * When using the u-boot FF-A  driver, any MM SP is supported.
> > + *
> >   * Return:		status code
> >   */
> >  static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> > @@ -162,7 +437,17 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> >  	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> >  	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
> >
> > -	ret = optee_mm_communicate(comm_buf, dsize);
> > +	ret = select_ffa_mm_comms();
> > +	if (ret != EFI_SUCCESS) {
> > +#if (IS_ENABLED(CONFIG_OPTEE))
> > +		ret = optee_mm_communicate(comm_buf, dsize);
> > +#endif
> > +	} else {
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +		ret = ffa_mm_communicate(comm_buf, dsize);
> > +#endif
> 
> This is a bit confusing to read.  Why does select_ffa_mm_comms() have to
> return and EFI return code?  It has nothing to do with EFI to begin with.
> 
> I think you can make select_ffa_mm_comms() return an enum with
> OPTEE/FFA. The you can rewrite this a bit cleaner
> Something along the lines of
> 
> efi_status_t ret = EFI_INVALID_PARAMETER;
> enum transport_select;
> 
> transport_select = select_ffa_mm_comms();
> if (transport_select == OPTEE)
>     ret = optee_mm_communicate(comm_buf, dsize);
> else
>     ret = ffa_mm_communicate(comm_buf, dsize);
> 
> While at it stub the ffa_mm_communicate() and optee_mm_communicate()
> functions so they are always defined but return EFI_UNSUPPORTED if the
> Kconfig is not selected while printing an appropriate error at the same
> time to inform the user which Kconfig option is missing.

Thanks. This is done in v11, please review.

Cheers,
Abdellatif

> 
> > +	}
> > +
> >  	if (ret != EFI_SUCCESS) {
> >  		log_err("%s failed!\n", __func__);
> >  		return ret;
> > @@ -258,6 +543,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
> >  		goto out;
> >  	}
> >  	*size = var_payload->size;
> > +
> > +	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
> > +			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
> > +				MM_VARIABLE_COMMUNICATE_SIZE;
> > +	#endif
> > +
> >  	/*
> >  	 * There seems to be a bug in EDK2 miscalculating the boundaries and
> >  	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> > @@ -697,7 +989,7 @@ void efi_variables_boot_exit_notify(void)
> >  		ret = EFI_NOT_FOUND;
> >
> >  	if (ret != EFI_SUCCESS)
> > -		log_err("Unable to notify StMM for ExitBootServices\n");
> > +		log_err("Unable to notify the MM partition for ExitBootServices\n");
> >  	free(comm_buf);
> >
> >  	/*
> > --
> > 2.25.1
> >
> 
> Thanks
> /Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 05/10] arm_ffa: introduce armffa command
  2023-04-12  9:42                                                                                           ` [PATCH v11 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-04-12 14:02                                                                                             ` Heinrich Schuchardt
  2023-04-12 15:53                                                                                               ` Abdellatif El Khlifi
  2023-04-19  1:49                                                                                             ` Simon Glass
  1 sibling, 1 reply; 478+ messages in thread
From: Heinrich Schuchardt @ 2023-04-12 14:02 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong

On 4/12/23 11:42, Abdellatif El Khlifi wrote:
> Provide armffa command showcasing the use of the U-Boot FF-A support
>
> armffa is a command showcasing how to invoke FF-A operations.
> This provides a guidance to the client developers on how to
> call the FF-A bus interfaces. The command also allows to gather secure
> partitions information and ping these  partitions. The command is also
> helpful in testing the communication with secure partitions.
>
> For more details please refer to the command documentation [1].
>
> [1]: doc/usage/cmd/armffa.rst
>
> 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>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
>
> ---
> Changelog:
> ===============
>
> v11:
>
> * use U_BOOT_CMD_WITH_SUBCMDS
> * address nits
>
> v10:
>
> * use the FF-A driver Uclass operations
> * use uclass_first_device()
> * address nits
>
> v9:
>
> * remove manual FF-A discovery and use DM
> * use DM class APIs to probe and interact with the FF-A bus
> * add doc/usage/cmd/armffa.rst
>
> v8:
>
> * update partition_info_get() second argument to be an SP count
> * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7:
>
> * adapt do_ffa_dev_list() following the recent update on
>    uclass_first_device/uclass_next_device functions (they return void now)
> * set armffa command to use 64-bit direct messaging
>
> v4:
>
> * remove pattern data in do_ffa_msg_send_direct_req
>
> v3:
>
> * use the new driver interfaces (partition_info_get, sync_send_receive)
>    in armffa command
>
> v2:
>
> * replace use of ffa_helper_init_device function by
>   ffa_helper_bus_discover
>
> v1:
>
> * introduce armffa command
>
>   MAINTAINERS                      |   2 +
>   cmd/Kconfig                      |  10 ++
>   cmd/Makefile                     |   2 +
>   cmd/armffa.c                     | 212 +++++++++++++++++++++++++++++++
>   doc/arch/arm64.ffa.rst           |   7 +
>   doc/usage/cmd/armffa.rst         | 105 +++++++++++++++
>   doc/usage/index.rst              |   1 +
>   drivers/firmware/arm-ffa/Kconfig |   1 +
>   8 files changed, 340 insertions(+)
>   create mode 100644 cmd/armffa.c
>   create mode 100644 doc/usage/cmd/armffa.rst
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 76f0f276ce..c64804ca2d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -269,7 +269,9 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
>   ARM FF-A
>   M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   S:	Maintained
> +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
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 8c9b430f99..4cb0b2c167 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -934,6 +934,16 @@ endmenu
>
>   menu "Device access commands"
>
> +config CMD_ARMFFA
> +	bool "Arm FF-A test command"
> +	depends on ARM_FFA_TRANSPORT
> +	help
> +	  Provides a test command for the FF-A support
> +	  supported options:
> +		- Listing the partition(s) info
> +		- Sending a data pattern to the specified partition
> +		- Displaying the arm_ffa device info
> +
>   config CMD_ARMFLASH
>   	#depends on FLASH_CFI_DRIVER
>   	bool "armflash"
> diff --git a/cmd/Makefile b/cmd/Makefile
> index e032091621..9130b9078d 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -12,6 +12,8 @@ obj-y += panic.o
>   obj-y += version.o
>
>   # command
> +
> +obj-$(CONFIG_CMD_ARMFFA) += armffa.o
>   obj-$(CONFIG_CMD_ACPI) += acpi.o
>   obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
>   obj-$(CONFIG_CMD_AES) += aes.o
> diff --git a/cmd/armffa.c b/cmd/armffa.c
> new file mode 100644
> index 0000000000..ab88412c7d
> --- /dev/null
> +++ b/cmd/armffa.c
> @@ -0,0 +1,212 @@
> +// 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 <command.h>
> +#include <dm.h>
> +#include <mapmem.h>
> +#include <stdlib.h>
> +#include <asm/io.h>
> +
> +/**
> + * ffa_get_dev() - Return the FF-A device
> + * @devp:	pointer to the FF-A device
> + *
> + * Search for the FF-A device.
> + *
> + * Return:
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_get_dev(struct udevice **devp)
> +{
> +	int ret;
> +
> +	ret = uclass_first_device_err(UCLASS_FFA, devp);
> +	if (ret) {
> +		log_err("Cannot find FF-A bus device\n");
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * do_ffa_getpart() - implementation of the getpart subcommand
> + * @cmdtp:		Command Table
> + * @flag:		flags
> + * @argc:		number of arguments
> + * @argv:		arguments
> + *
> + * Query the secure partition information which the UUID is provided
> + * as an argument. The function uses the arm_ffa driver
> + * partition_info_get operation which implements FFA_PARTITION_INFO_GET
> + * ABI to retrieve the data. The input UUID string is expected to be in big
> + * endian format.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
> +			  char *const argv[])
> +{
> +	u32 count = 0;
> +	int ret;
> +	struct ffa_partition_info *parts_info;
> +	u32 i;
> +	struct udevice *dev;
> +
> +	ret = ffa_get_dev(&dev);
> +	if (ret)
> +		return CMD_RET_FAILURE;
> +
> +	/* Mode 1: getting the number of secure partitions */
> +	ret = ffa_partition_info_get(dev, argv[1], &count, NULL);
> +	if (ret) {
> +		log_err("Failure in querying partitions count (error code: %d)\n", ret);
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	if (!count) {
> +		log_info("No secure partition found\n");
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	/*
> +	 * Pre-allocate a buffer to be filled by the driver
> +	 * with ffa_partition_info structs
> +	 */
> +
> +	log_info("Pre-allocating %d partition(s) info structures\n", count);
> +
> +	parts_info = calloc(count, sizeof(struct ffa_partition_info));
> +	if (!parts_info)
> +		return CMD_RET_FAILURE;
> +
> +	/* Ask the driver to fill the buffer with the SPs info */
> +
> +	ret = ffa_partition_info_get(dev, argv[1], &count, parts_info);
> +	if (ret) {
> +		log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
> +		free(parts_info);
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	/* SPs found , show the partition information */
> +	for (i = 0; i < count ; i++) {
> +		log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
> +			 parts_info[i].id,
> +			 parts_info[i].exec_ctxt,
> +			 parts_info[i].properties);
> +	}
> +
> +	free(parts_info);
> +
> +	return CMD_RET_SUCCESS;
> +}
> +
> +/**
> + * do_ffa_ping() - implementation of the ping subcommand
> + * @cmdtp:		Command Table
> + * @flag:		flags
> + * @argc:		number of arguments
> + * @argv:		arguments
> + *
> + * Send data to the secure partition which the ID is provided
> + * as an argument. Use the arm_ffa driver sync_send_receive operation
> + * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +	struct ffa_send_direct_data msg = {
> +			.data0 = 0xaaaaaaaa,
> +			.data1 = 0xbbbbbbbb,
> +			.data2 = 0xcccccccc,
> +			.data3 = 0xdddddddd,
> +			.data4 = 0xeeeeeeee,
> +	};
> +	u16 part_id;
> +	int ret;
> +	struct udevice *dev;
> +
> +	errno = 0;
> +	part_id = strtoul(argv[1], NULL, 16);
> +
> +	if (errno) {
> +		log_err("Invalid partition ID\n");
> +		return CMD_RET_USAGE;
> +	}
> +
> +	ret = ffa_get_dev(&dev);
> +	if (ret)
> +		return CMD_RET_FAILURE;
> +
> +	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
> +	if (!ret) {
> +		u8 cnt;
> +
> +		log_info("SP response:\n[LSB]\n");
> +		for (cnt = 0;
> +		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
> +		     cnt++)
> +			log_info("%llx\n", ((u64 *)&msg)[cnt]);
> +		return CMD_RET_SUCCESS;
> +	}
> +
> +	log_err("Sending direct request error (%d)\n", ret);
> +	return CMD_RET_FAILURE;
> +}
> +
> +/**
> + *do_ffa_devlist() - implementation of the devlist subcommand
> + * @cmdtp: [in]		Command Table
> + * @flag:		flags
> + * @argc:		number of arguments
> + * @argv:		arguments
> + *
> + * Query the device belonging to the UCLASS_FFA
> + * class.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +	struct udevice *dev;
> +	int ret;
> +
> +	ret = ffa_get_dev(&dev);
> +	if (ret)
> +		return CMD_RET_FAILURE;
> +
> +	log_info("device name %s, dev %p, driver name %s, ops %p\n",
> +		 dev->name,
> +		(void *)map_to_sysmem(dev),
> +		 dev->driver->name,
> +		 (void *)map_to_sysmem(dev->driver->ops));
> +
> +	return CMD_RET_SUCCESS;
> +}
> +
> +static char armffa_help_text[] =
> +	"getpart <partition UUID>\n"
> +	"       - lists the partition(s) info\n"
> +	"ping <partition ID>\n"
> +	"       - sends a data pattern to the specified partition\n"
> +	"devlist\n"
> +	"       - displays information about the FF-A device/driver\n";
> +
> +U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
> +			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
> +			U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping),
> +			U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist));
> diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> index 466e77e3cd..ed7240aef7 100644
> --- a/doc/arch/arm64.ffa.rst
> +++ b/doc/arch/arm64.ffa.rst
> @@ -216,6 +216,13 @@ The following features are provided:
>
>   - FF-A bus can be compiled and used without EFI
>
> +The armffa command
> +-----------------------------------
> +
> +armffa is an implementation defined command showcasing how to use the FF-A bus and how to invoke the driver operations.
> +
> +Please refer the command documentation at doc/usage/cmd/armffa.rst
> +
>   Example of boot logs with FF-A enabled
>   --------------------------------------
>
> diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
> new file mode 100644
> index 0000000000..e73d03ae51
> --- /dev/null
> +++ b/doc/usage/cmd/armffa.rst
> @@ -0,0 +1,105 @@
> +.. SPDX-License-Identifier: GPL-2.0+:
> +
> +armffa command
> +==============
> +
> +Synopsis
> +--------
> +
> +::
> +
> +   armffa [sub-command] [arguments]
> +
> +   sub-commands:
> +
> +        getpart [partition UUID]
> +
> +            lists the partition(s) info
> +
> +        ping [partition ID]
> +
> +            sends a data pattern to the specified partition
> +
> +        devlist
> +
> +            displays information about the FF-A device/driver
> +
> +Description
> +-----------
> +
> +armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
> +
> +This provides a guidance to the client developers on how to call the FF-A bus interfaces.
> +
> +The command also allows to gather secure partitions information and ping these  partitions.
> +
> +The command is also helpful in testing the communication with secure partitions.
> +
> +Example
> +-------
> +
> +The following examples are run on Corstone-1000 platform with debug logs enabled.
> +
> +* ping
> +
> +::
> +
> +   corstone1000# armffa ping 0x8003
> +   SP response:
> +   [LSB]
> +   fffffffe
> +   0
> +   0
> +   0
> +   0
> +
> +* ping (failure case)
> +
> +::
> +
> +   corstone1000# armffa ping 0
> +   Sending direct request error (-22)
> +
> +* getpart
> +
> +::
> +
> +   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
> +   Preparing for checking FF-A partitions count
> +   Searching FF-A partitions using the provided UUID
> +   No FF-A partition found. Querying framework ...
> +   Reading FF-A partitions data from the RX buffer
> +   Number of FF-A partition(s) matching the UUID: 1
> +   Pre-allocating 1 partition(s) info structures
> +   Preparing for filling FF-A partitions info
> +   Searching FF-A partitions using the provided UUID
> +   FF-A partition ID 8003 matches the provided UUID
> +   Partition: id = 8003 , exec_ctxt 1 , properties 3
> +
> +* getpart (failure case)
> +
> +::
> +
> +   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221
> +   Preparing for checking FF-A partitions count
> +   Searching FF-A partitions using the provided UUID
> +   No FF-A partition found. Querying framework ...
> +   INVALID_PARAMETERS: Unrecognized UUID
> +   Failure in querying partitions count (error code: -22)
> +
> +* devlist
> +
> +::
> +
> +   corstone1000# armffa devlist
> +   device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98
> +
> +Configuration
> +-------------
> +
> +The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
> +
> +Return value
> +------------
> +
> +The return value $? is 0 (true) on success and a negative error code on failure.

CMD_RET_FAILURE results in $? being 1 (false). Did you actually see a
negative value?

Best regards

Heinrich


> diff --git a/doc/usage/index.rst b/doc/usage/index.rst
> index bc85e1d49a..df107fb710 100644
> --- a/doc/usage/index.rst
> +++ b/doc/usage/index.rst
> @@ -21,6 +21,7 @@ Shell commands
>
>      cmd/acpi
>      cmd/addrmap
> +   cmd/armffa
>      cmd/askenv
>      cmd/base
>      cmd/bdinfo
> diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> index 9200c8028b..a7d5392859 100644
> --- a/drivers/firmware/arm-ffa/Kconfig
> +++ b/drivers/firmware/arm-ffa/Kconfig
> @@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
>   	depends on DM && ARM64
>   	select ARM_SMCCC
>   	select ARM_SMCCC_FEATURES
> +	imply CMD_ARMFFA
>   	select LIB_UUID
>   	select DEVRES
>   	help


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 05/10] arm_ffa: introduce armffa command
  2023-04-12 14:02                                                                                             ` Heinrich Schuchardt
@ 2023-04-12 15:53                                                                                               ` Abdellatif El Khlifi
  2023-04-12 20:00                                                                                                 ` Heinrich Schuchardt
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-12 15:53 UTC (permalink / raw)
  To: Heinrich Schuchardt; +Cc: nd, u-boot

On Wed, Apr 12, 2023 at 04:02:43PM +0200, Heinrich Schuchardt wrote:
> On 4/12/23 11:42, Abdellatif El Khlifi wrote:
> > Provide armffa command showcasing the use of the U-Boot FF-A support
> > 
> > armffa is a command showcasing how to invoke FF-A operations.
> > This provides a guidance to the client developers on how to
> > call the FF-A bus interfaces. The command also allows to gather secure
> > partitions information and ping these  partitions. The command is also
> > helpful in testing the communication with secure partitions.
> > 
> > For more details please refer to the command documentation [1].
> > 
> > [1]: doc/usage/cmd/armffa.rst
> > 
> > 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>
> > Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
> > 
> > ---
> > Changelog:
> > ===============
> > 
> > v11:
> > 
> > * use U_BOOT_CMD_WITH_SUBCMDS
> > * address nits
> > 
> > v10:
> > 
> > * use the FF-A driver Uclass operations
> > * use uclass_first_device()
> > * address nits
> > 
> > v9:
> > 
> > * remove manual FF-A discovery and use DM
> > * use DM class APIs to probe and interact with the FF-A bus
> > * add doc/usage/cmd/armffa.rst
> > 
> > v8:
> > 
> > * update partition_info_get() second argument to be an SP count
> > * pass NULL device pointer to the FF-A bus discovery and operations
> > 
> > v7:
> > 
> > * adapt do_ffa_dev_list() following the recent update on
> >    uclass_first_device/uclass_next_device functions (they return void now)
> > * set armffa command to use 64-bit direct messaging
> > 
> > v4:
> > 
> > * remove pattern data in do_ffa_msg_send_direct_req
> > 
> > v3:
> > 
> > * use the new driver interfaces (partition_info_get, sync_send_receive)
> >    in armffa command
> > 
> > v2:
> > 
> > * replace use of ffa_helper_init_device function by
> >   ffa_helper_bus_discover
> > 
> > v1:
> > 
> > * introduce armffa command
> > 
> >   MAINTAINERS                      |   2 +
> >   cmd/Kconfig                      |  10 ++
> >   cmd/Makefile                     |   2 +
> >   cmd/armffa.c                     | 212 +++++++++++++++++++++++++++++++
> >   doc/arch/arm64.ffa.rst           |   7 +
> >   doc/usage/cmd/armffa.rst         | 105 +++++++++++++++
> >   doc/usage/index.rst              |   1 +
> >   drivers/firmware/arm-ffa/Kconfig |   1 +
> >   8 files changed, 340 insertions(+)
> >   create mode 100644 cmd/armffa.c
> >   create mode 100644 doc/usage/cmd/armffa.rst
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 76f0f276ce..c64804ca2d 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -269,7 +269,9 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
> >   ARM FF-A
> >   M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   S:	Maintained
> > +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
> > diff --git a/cmd/Kconfig b/cmd/Kconfig
> > index 8c9b430f99..4cb0b2c167 100644
> > --- a/cmd/Kconfig
> > +++ b/cmd/Kconfig
> > @@ -934,6 +934,16 @@ endmenu
> > 
> >   menu "Device access commands"
> > 
> > +config CMD_ARMFFA
> > +	bool "Arm FF-A test command"
> > +	depends on ARM_FFA_TRANSPORT
> > +	help
> > +	  Provides a test command for the FF-A support
> > +	  supported options:
> > +		- Listing the partition(s) info
> > +		- Sending a data pattern to the specified partition
> > +		- Displaying the arm_ffa device info
> > +
> >   config CMD_ARMFLASH
> >   	#depends on FLASH_CFI_DRIVER
> >   	bool "armflash"
> > diff --git a/cmd/Makefile b/cmd/Makefile
> > index e032091621..9130b9078d 100644
> > --- a/cmd/Makefile
> > +++ b/cmd/Makefile
> > @@ -12,6 +12,8 @@ obj-y += panic.o
> >   obj-y += version.o
> > 
> >   # command
> > +
> > +obj-$(CONFIG_CMD_ARMFFA) += armffa.o
> >   obj-$(CONFIG_CMD_ACPI) += acpi.o
> >   obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
> >   obj-$(CONFIG_CMD_AES) += aes.o
> > diff --git a/cmd/armffa.c b/cmd/armffa.c
> > new file mode 100644
> > index 0000000000..ab88412c7d
> > --- /dev/null
> > +++ b/cmd/armffa.c
> > @@ -0,0 +1,212 @@
> > +// 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 <command.h>
> > +#include <dm.h>
> > +#include <mapmem.h>
> > +#include <stdlib.h>
> > +#include <asm/io.h>
> > +
> > +/**
> > + * ffa_get_dev() - Return the FF-A device
> > + * @devp:	pointer to the FF-A device
> > + *
> > + * Search for the FF-A device.
> > + *
> > + * Return:
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_get_dev(struct udevice **devp)
> > +{
> > +	int ret;
> > +
> > +	ret = uclass_first_device_err(UCLASS_FFA, devp);
> > +	if (ret) {
> > +		log_err("Cannot find FF-A bus device\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * do_ffa_getpart() - implementation of the getpart subcommand
> > + * @cmdtp:		Command Table
> > + * @flag:		flags
> > + * @argc:		number of arguments
> > + * @argv:		arguments
> > + *
> > + * Query the secure partition information which the UUID is provided
> > + * as an argument. The function uses the arm_ffa driver
> > + * partition_info_get operation which implements FFA_PARTITION_INFO_GET
> > + * ABI to retrieve the data. The input UUID string is expected to be in big
> > + * endian format.
> > + *
> > + * Return:
> > + *
> > + * CMD_RET_SUCCESS: on success, otherwise failure
> > + */
> > +static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
> > +			  char *const argv[])
> > +{
> > +	u32 count = 0;
> > +	int ret;
> > +	struct ffa_partition_info *parts_info;
> > +	u32 i;
> > +	struct udevice *dev;
> > +
> > +	ret = ffa_get_dev(&dev);
> > +	if (ret)
> > +		return CMD_RET_FAILURE;
> > +
> > +	/* Mode 1: getting the number of secure partitions */
> > +	ret = ffa_partition_info_get(dev, argv[1], &count, NULL);
> > +	if (ret) {
> > +		log_err("Failure in querying partitions count (error code: %d)\n", ret);
> > +		return CMD_RET_FAILURE;
> > +	}
> > +
> > +	if (!count) {
> > +		log_info("No secure partition found\n");
> > +		return CMD_RET_FAILURE;
> > +	}
> > +
> > +	/*
> > +	 * Pre-allocate a buffer to be filled by the driver
> > +	 * with ffa_partition_info structs
> > +	 */
> > +
> > +	log_info("Pre-allocating %d partition(s) info structures\n", count);
> > +
> > +	parts_info = calloc(count, sizeof(struct ffa_partition_info));
> > +	if (!parts_info)
> > +		return CMD_RET_FAILURE;
> > +
> > +	/* Ask the driver to fill the buffer with the SPs info */
> > +
> > +	ret = ffa_partition_info_get(dev, argv[1], &count, parts_info);
> > +	if (ret) {
> > +		log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
> > +		free(parts_info);
> > +		return CMD_RET_FAILURE;
> > +	}
> > +
> > +	/* SPs found , show the partition information */
> > +	for (i = 0; i < count ; i++) {
> > +		log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
> > +			 parts_info[i].id,
> > +			 parts_info[i].exec_ctxt,
> > +			 parts_info[i].properties);
> > +	}
> > +
> > +	free(parts_info);
> > +
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +/**
> > + * do_ffa_ping() - implementation of the ping subcommand
> > + * @cmdtp:		Command Table
> > + * @flag:		flags
> > + * @argc:		number of arguments
> > + * @argv:		arguments
> > + *
> > + * Send data to the secure partition which the ID is provided
> > + * as an argument. Use the arm_ffa driver sync_send_receive operation
> > + * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
> > + *
> > + * Return:
> > + *
> > + * CMD_RET_SUCCESS: on success, otherwise failure
> > + */
> > +int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > +{
> > +	struct ffa_send_direct_data msg = {
> > +			.data0 = 0xaaaaaaaa,
> > +			.data1 = 0xbbbbbbbb,
> > +			.data2 = 0xcccccccc,
> > +			.data3 = 0xdddddddd,
> > +			.data4 = 0xeeeeeeee,
> > +	};
> > +	u16 part_id;
> > +	int ret;
> > +	struct udevice *dev;
> > +
> > +	errno = 0;
> > +	part_id = strtoul(argv[1], NULL, 16);
> > +
> > +	if (errno) {
> > +		log_err("Invalid partition ID\n");
> > +		return CMD_RET_USAGE;
> > +	}
> > +
> > +	ret = ffa_get_dev(&dev);
> > +	if (ret)
> > +		return CMD_RET_FAILURE;
> > +
> > +	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
> > +	if (!ret) {
> > +		u8 cnt;
> > +
> > +		log_info("SP response:\n[LSB]\n");
> > +		for (cnt = 0;
> > +		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
> > +		     cnt++)
> > +			log_info("%llx\n", ((u64 *)&msg)[cnt]);
> > +		return CMD_RET_SUCCESS;
> > +	}
> > +
> > +	log_err("Sending direct request error (%d)\n", ret);
> > +	return CMD_RET_FAILURE;
> > +}
> > +
> > +/**
> > + *do_ffa_devlist() - implementation of the devlist subcommand
> > + * @cmdtp: [in]		Command Table
> > + * @flag:		flags
> > + * @argc:		number of arguments
> > + * @argv:		arguments
> > + *
> > + * Query the device belonging to the UCLASS_FFA
> > + * class.
> > + *
> > + * Return:
> > + *
> > + * CMD_RET_SUCCESS: on success, otherwise failure
> > + */
> > +int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > +{
> > +	struct udevice *dev;
> > +	int ret;
> > +
> > +	ret = ffa_get_dev(&dev);
> > +	if (ret)
> > +		return CMD_RET_FAILURE;
> > +
> > +	log_info("device name %s, dev %p, driver name %s, ops %p\n",
> > +		 dev->name,
> > +		(void *)map_to_sysmem(dev),
> > +		 dev->driver->name,
> > +		 (void *)map_to_sysmem(dev->driver->ops));
> > +
> > +	return CMD_RET_SUCCESS;
> > +}
> > +
> > +static char armffa_help_text[] =
> > +	"getpart <partition UUID>\n"
> > +	"       - lists the partition(s) info\n"
> > +	"ping <partition ID>\n"
> > +	"       - sends a data pattern to the specified partition\n"
> > +	"devlist\n"
> > +	"       - displays information about the FF-A device/driver\n";
> > +
> > +U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
> > +			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
> > +			U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping),
> > +			U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist));
> > diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> > index 466e77e3cd..ed7240aef7 100644
> > --- a/doc/arch/arm64.ffa.rst
> > +++ b/doc/arch/arm64.ffa.rst
> > @@ -216,6 +216,13 @@ The following features are provided:
> > 
> >   - FF-A bus can be compiled and used without EFI
> > 
> > +The armffa command
> > +-----------------------------------
> > +
> > +armffa is an implementation defined command showcasing how to use the FF-A bus and how to invoke the driver operations.
> > +
> > +Please refer the command documentation at doc/usage/cmd/armffa.rst
> > +
> >   Example of boot logs with FF-A enabled
> >   --------------------------------------
> > 
> > diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
> > new file mode 100644
> > index 0000000000..e73d03ae51
> > --- /dev/null
> > +++ b/doc/usage/cmd/armffa.rst
> > @@ -0,0 +1,105 @@
> > +.. SPDX-License-Identifier: GPL-2.0+:
> > +
> > +armffa command
> > +==============
> > +
> > +Synopsis
> > +--------
> > +
> > +::
> > +
> > +   armffa [sub-command] [arguments]
> > +
> > +   sub-commands:
> > +
> > +        getpart [partition UUID]
> > +
> > +            lists the partition(s) info
> > +
> > +        ping [partition ID]
> > +
> > +            sends a data pattern to the specified partition
> > +
> > +        devlist
> > +
> > +            displays information about the FF-A device/driver
> > +
> > +Description
> > +-----------
> > +
> > +armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
> > +
> > +This provides a guidance to the client developers on how to call the FF-A bus interfaces.
> > +
> > +The command also allows to gather secure partitions information and ping these  partitions.
> > +
> > +The command is also helpful in testing the communication with secure partitions.
> > +
> > +Example
> > +-------
> > +
> > +The following examples are run on Corstone-1000 platform with debug logs enabled.
> > +
> > +* ping
> > +
> > +::
> > +
> > +   corstone1000# armffa ping 0x8003
> > +   SP response:
> > +   [LSB]
> > +   fffffffe
> > +   0
> > +   0
> > +   0
> > +   0
> > +
> > +* ping (failure case)
> > +
> > +::
> > +
> > +   corstone1000# armffa ping 0
> > +   Sending direct request error (-22)
> > +
> > +* getpart
> > +
> > +::
> > +
> > +   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
> > +   Preparing for checking FF-A partitions count
> > +   Searching FF-A partitions using the provided UUID
> > +   No FF-A partition found. Querying framework ...
> > +   Reading FF-A partitions data from the RX buffer
> > +   Number of FF-A partition(s) matching the UUID: 1
> > +   Pre-allocating 1 partition(s) info structures
> > +   Preparing for filling FF-A partitions info
> > +   Searching FF-A partitions using the provided UUID
> > +   FF-A partition ID 8003 matches the provided UUID
> > +   Partition: id = 8003 , exec_ctxt 1 , properties 3
> > +
> > +* getpart (failure case)
> > +
> > +::
> > +
> > +   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221
> > +   Preparing for checking FF-A partitions count
> > +   Searching FF-A partitions using the provided UUID
> > +   No FF-A partition found. Querying framework ...
> > +   INVALID_PARAMETERS: Unrecognized UUID
> > +   Failure in querying partitions count (error code: -22)
> > +
> > +* devlist
> > +
> > +::
> > +
> > +   corstone1000# armffa devlist
> > +   device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98
> > +
> > +Configuration
> > +-------------
> > +
> > +The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
> > +
> > +Return value
> > +------------
> > +
> > +The return value $? is 0 (true) on success and a negative error code on failure.
> 
> CMD_RET_FAILURE results in $? being 1 (false). Did you actually see a
> negative value?

For armffa, the possible return codes are: CMD_RET_USAGE (-1), CMD_RET_FAILURE (1) and CMD_RET_SUCCESS (0)

I suggest replacing the sentence with:

The return value $? is 0 (true) on success, -1 on usage error and 1 (false) on FF-A related failures.

Cheers
Abdellatif

> 
> Best regards
> 
> Heinrich
> 
> 
> > diff --git a/doc/usage/index.rst b/doc/usage/index.rst
> > index bc85e1d49a..df107fb710 100644
> > --- a/doc/usage/index.rst
> > +++ b/doc/usage/index.rst
> > @@ -21,6 +21,7 @@ Shell commands
> > 
> >      cmd/acpi
> >      cmd/addrmap
> > +   cmd/armffa
> >      cmd/askenv
> >      cmd/base
> >      cmd/bdinfo
> > diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> > index 9200c8028b..a7d5392859 100644
> > --- a/drivers/firmware/arm-ffa/Kconfig
> > +++ b/drivers/firmware/arm-ffa/Kconfig
> > @@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
> >   	depends on DM && ARM64
> >   	select ARM_SMCCC
> >   	select ARM_SMCCC_FEATURES
> > +	imply CMD_ARMFFA
> >   	select LIB_UUID
> >   	select DEVRES
> >   	help
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 05/10] arm_ffa: introduce armffa command
  2023-04-12 15:53                                                                                               ` Abdellatif El Khlifi
@ 2023-04-12 20:00                                                                                                 ` Heinrich Schuchardt
  2023-04-13 10:15                                                                                                   ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Heinrich Schuchardt @ 2023-04-12 20:00 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: nd, u-boot



Am 12. April 2023 17:53:23 MESZ schrieb Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>:
>On Wed, Apr 12, 2023 at 04:02:43PM +0200, Heinrich Schuchardt wrote:
>> On 4/12/23 11:42, Abdellatif El Khlifi wrote:
>> > Provide armffa command showcasing the use of the U-Boot FF-A support
>> > 
>> > armffa is a command showcasing how to invoke FF-A operations.
>> > This provides a guidance to the client developers on how to
>> > call the FF-A bus interfaces. The command also allows to gather secure
>> > partitions information and ping these  partitions. The command is also
>> > helpful in testing the communication with secure partitions.
>> > 
>> > For more details please refer to the command documentation [1].
>> > 
>> > [1]: doc/usage/cmd/armffa.rst
>> > 
>> > 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>
>> > Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
>> > 
>> > ---
>> > Changelog:
>> > ===============
>> > 
>> > v11:
>> > 
>> > * use U_BOOT_CMD_WITH_SUBCMDS
>> > * address nits
>> > 
>> > v10:
>> > 
>> > * use the FF-A driver Uclass operations
>> > * use uclass_first_device()
>> > * address nits
>> > 
>> > v9:
>> > 
>> > * remove manual FF-A discovery and use DM
>> > * use DM class APIs to probe and interact with the FF-A bus
>> > * add doc/usage/cmd/armffa.rst
>> > 
>> > v8:
>> > 
>> > * update partition_info_get() second argument to be an SP count
>> > * pass NULL device pointer to the FF-A bus discovery and operations
>> > 
>> > v7:
>> > 
>> > * adapt do_ffa_dev_list() following the recent update on
>> >    uclass_first_device/uclass_next_device functions (they return void now)
>> > * set armffa command to use 64-bit direct messaging
>> > 
>> > v4:
>> > 
>> > * remove pattern data in do_ffa_msg_send_direct_req
>> > 
>> > v3:
>> > 
>> > * use the new driver interfaces (partition_info_get, sync_send_receive)
>> >    in armffa command
>> > 
>> > v2:
>> > 
>> > * replace use of ffa_helper_init_device function by
>> >   ffa_helper_bus_discover
>> > 
>> > v1:
>> > 
>> > * introduce armffa command
>> > 
>> >   MAINTAINERS                      |   2 +
>> >   cmd/Kconfig                      |  10 ++
>> >   cmd/Makefile                     |   2 +
>> >   cmd/armffa.c                     | 212 +++++++++++++++++++++++++++++++
>> >   doc/arch/arm64.ffa.rst           |   7 +
>> >   doc/usage/cmd/armffa.rst         | 105 +++++++++++++++
>> >   doc/usage/index.rst              |   1 +
>> >   drivers/firmware/arm-ffa/Kconfig |   1 +
>> >   8 files changed, 340 insertions(+)
>> >   create mode 100644 cmd/armffa.c
>> >   create mode 100644 doc/usage/cmd/armffa.rst
>> > 
>> > diff --git a/MAINTAINERS b/MAINTAINERS
>> > index 76f0f276ce..c64804ca2d 100644
>> > --- a/MAINTAINERS
>> > +++ b/MAINTAINERS
>> > @@ -269,7 +269,9 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
>> >   ARM FF-A
>> >   M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>> >   S:	Maintained
>> > +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
>> > diff --git a/cmd/Kconfig b/cmd/Kconfig
>> > index 8c9b430f99..4cb0b2c167 100644
>> > --- a/cmd/Kconfig
>> > +++ b/cmd/Kconfig
>> > @@ -934,6 +934,16 @@ endmenu
>> > 
>> >   menu "Device access commands"
>> > 
>> > +config CMD_ARMFFA
>> > +	bool "Arm FF-A test command"
>> > +	depends on ARM_FFA_TRANSPORT
>> > +	help
>> > +	  Provides a test command for the FF-A support
>> > +	  supported options:
>> > +		- Listing the partition(s) info
>> > +		- Sending a data pattern to the specified partition
>> > +		- Displaying the arm_ffa device info
>> > +
>> >   config CMD_ARMFLASH
>> >   	#depends on FLASH_CFI_DRIVER
>> >   	bool "armflash"
>> > diff --git a/cmd/Makefile b/cmd/Makefile
>> > index e032091621..9130b9078d 100644
>> > --- a/cmd/Makefile
>> > +++ b/cmd/Makefile
>> > @@ -12,6 +12,8 @@ obj-y += panic.o
>> >   obj-y += version.o
>> > 
>> >   # command
>> > +
>> > +obj-$(CONFIG_CMD_ARMFFA) += armffa.o
>> >   obj-$(CONFIG_CMD_ACPI) += acpi.o
>> >   obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
>> >   obj-$(CONFIG_CMD_AES) += aes.o
>> > diff --git a/cmd/armffa.c b/cmd/armffa.c
>> > new file mode 100644
>> > index 0000000000..ab88412c7d
>> > --- /dev/null
>> > +++ b/cmd/armffa.c
>> > @@ -0,0 +1,212 @@
>> > +// 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 <command.h>
>> > +#include <dm.h>
>> > +#include <mapmem.h>
>> > +#include <stdlib.h>
>> > +#include <asm/io.h>
>> > +
>> > +/**
>> > + * ffa_get_dev() - Return the FF-A device
>> > + * @devp:	pointer to the FF-A device
>> > + *
>> > + * Search for the FF-A device.
>> > + *
>> > + * Return:
>> > + * 0 on success. Otherwise, failure
>> > + */
>> > +int ffa_get_dev(struct udevice **devp)
>> > +{
>> > +	int ret;
>> > +
>> > +	ret = uclass_first_device_err(UCLASS_FFA, devp);
>> > +	if (ret) {
>> > +		log_err("Cannot find FF-A bus device\n");
>> > +		return -ENODEV;
>> > +	}
>> > +
>> > +	return 0;
>> > +}
>> > +
>> > +/**
>> > + * do_ffa_getpart() - implementation of the getpart subcommand
>> > + * @cmdtp:		Command Table
>> > + * @flag:		flags
>> > + * @argc:		number of arguments
>> > + * @argv:		arguments
>> > + *
>> > + * Query the secure partition information which the UUID is provided
>> > + * as an argument. The function uses the arm_ffa driver
>> > + * partition_info_get operation which implements FFA_PARTITION_INFO_GET
>> > + * ABI to retrieve the data. The input UUID string is expected to be in big
>> > + * endian format.
>> > + *
>> > + * Return:
>> > + *
>> > + * CMD_RET_SUCCESS: on success, otherwise failure
>> > + */
>> > +static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
>> > +			  char *const argv[])
>> > +{
>> > +	u32 count = 0;
>> > +	int ret;
>> > +	struct ffa_partition_info *parts_info;
>> > +	u32 i;
>> > +	struct udevice *dev;
>> > +
>> > +	ret = ffa_get_dev(&dev);
>> > +	if (ret)
>> > +		return CMD_RET_FAILURE;
>> > +
>> > +	/* Mode 1: getting the number of secure partitions */
>> > +	ret = ffa_partition_info_get(dev, argv[1], &count, NULL);
>> > +	if (ret) {
>> > +		log_err("Failure in querying partitions count (error code: %d)\n", ret);
>> > +		return CMD_RET_FAILURE;
>> > +	}
>> > +
>> > +	if (!count) {
>> > +		log_info("No secure partition found\n");
>> > +		return CMD_RET_FAILURE;
>> > +	}
>> > +
>> > +	/*
>> > +	 * Pre-allocate a buffer to be filled by the driver
>> > +	 * with ffa_partition_info structs
>> > +	 */
>> > +
>> > +	log_info("Pre-allocating %d partition(s) info structures\n", count);
>> > +
>> > +	parts_info = calloc(count, sizeof(struct ffa_partition_info));
>> > +	if (!parts_info)
>> > +		return CMD_RET_FAILURE;
>> > +
>> > +	/* Ask the driver to fill the buffer with the SPs info */
>> > +
>> > +	ret = ffa_partition_info_get(dev, argv[1], &count, parts_info);
>> > +	if (ret) {
>> > +		log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
>> > +		free(parts_info);
>> > +		return CMD_RET_FAILURE;
>> > +	}
>> > +
>> > +	/* SPs found , show the partition information */
>> > +	for (i = 0; i < count ; i++) {
>> > +		log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
>> > +			 parts_info[i].id,
>> > +			 parts_info[i].exec_ctxt,
>> > +			 parts_info[i].properties);
>> > +	}
>> > +
>> > +	free(parts_info);
>> > +
>> > +	return CMD_RET_SUCCESS;
>> > +}
>> > +
>> > +/**
>> > + * do_ffa_ping() - implementation of the ping subcommand
>> > + * @cmdtp:		Command Table
>> > + * @flag:		flags
>> > + * @argc:		number of arguments
>> > + * @argv:		arguments
>> > + *
>> > + * Send data to the secure partition which the ID is provided
>> > + * as an argument. Use the arm_ffa driver sync_send_receive operation
>> > + * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
>> > + *
>> > + * Return:
>> > + *
>> > + * CMD_RET_SUCCESS: on success, otherwise failure
>> > + */
>> > +int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>> > +{
>> > +	struct ffa_send_direct_data msg = {
>> > +			.data0 = 0xaaaaaaaa,
>> > +			.data1 = 0xbbbbbbbb,
>> > +			.data2 = 0xcccccccc,
>> > +			.data3 = 0xdddddddd,
>> > +			.data4 = 0xeeeeeeee,
>> > +	};
>> > +	u16 part_id;
>> > +	int ret;
>> > +	struct udevice *dev;
>> > +
>> > +	errno = 0;
>> > +	part_id = strtoul(argv[1], NULL, 16);
>> > +
>> > +	if (errno) {
>> > +		log_err("Invalid partition ID\n");
>> > +		return CMD_RET_USAGE;
>> > +	}
>> > +
>> > +	ret = ffa_get_dev(&dev);
>> > +	if (ret)
>> > +		return CMD_RET_FAILURE;
>> > +
>> > +	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
>> > +	if (!ret) {
>> > +		u8 cnt;
>> > +
>> > +		log_info("SP response:\n[LSB]\n");
>> > +		for (cnt = 0;
>> > +		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
>> > +		     cnt++)
>> > +			log_info("%llx\n", ((u64 *)&msg)[cnt]);
>> > +		return CMD_RET_SUCCESS;
>> > +	}
>> > +
>> > +	log_err("Sending direct request error (%d)\n", ret);
>> > +	return CMD_RET_FAILURE;
>> > +}
>> > +
>> > +/**
>> > + *do_ffa_devlist() - implementation of the devlist subcommand
>> > + * @cmdtp: [in]		Command Table
>> > + * @flag:		flags
>> > + * @argc:		number of arguments
>> > + * @argv:		arguments
>> > + *
>> > + * Query the device belonging to the UCLASS_FFA
>> > + * class.
>> > + *
>> > + * Return:
>> > + *
>> > + * CMD_RET_SUCCESS: on success, otherwise failure
>> > + */
>> > +int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>> > +{
>> > +	struct udevice *dev;
>> > +	int ret;
>> > +
>> > +	ret = ffa_get_dev(&dev);
>> > +	if (ret)
>> > +		return CMD_RET_FAILURE;
>> > +
>> > +	log_info("device name %s, dev %p, driver name %s, ops %p\n",
>> > +		 dev->name,
>> > +		(void *)map_to_sysmem(dev),
>> > +		 dev->driver->name,
>> > +		 (void *)map_to_sysmem(dev->driver->ops));
>> > +
>> > +	return CMD_RET_SUCCESS;
>> > +}
>> > +
>> > +static char armffa_help_text[] =
>> > +	"getpart <partition UUID>\n"
>> > +	"       - lists the partition(s) info\n"
>> > +	"ping <partition ID>\n"
>> > +	"       - sends a data pattern to the specified partition\n"
>> > +	"devlist\n"
>> > +	"       - displays information about the FF-A device/driver\n";
>> > +
>> > +U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
>> > +			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
>> > +			U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping),
>> > +			U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist));
>> > diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
>> > index 466e77e3cd..ed7240aef7 100644
>> > --- a/doc/arch/arm64.ffa.rst
>> > +++ b/doc/arch/arm64.ffa.rst
>> > @@ -216,6 +216,13 @@ The following features are provided:
>> > 
>> >   - FF-A bus can be compiled and used without EFI
>> > 
>> > +The armffa command
>> > +-----------------------------------
>> > +
>> > +armffa is an implementation defined command showcasing how to use the FF-A bus and how to invoke the driver operations.
>> > +
>> > +Please refer the command documentation at doc/usage/cmd/armffa.rst
>> > +
>> >   Example of boot logs with FF-A enabled
>> >   --------------------------------------
>> > 
>> > diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
>> > new file mode 100644
>> > index 0000000000..e73d03ae51
>> > --- /dev/null
>> > +++ b/doc/usage/cmd/armffa.rst
>> > @@ -0,0 +1,105 @@
>> > +.. SPDX-License-Identifier: GPL-2.0+:
>> > +
>> > +armffa command
>> > +==============
>> > +
>> > +Synopsis
>> > +--------
>> > +
>> > +::
>> > +
>> > +   armffa [sub-command] [arguments]
>> > +
>> > +   sub-commands:
>> > +
>> > +        getpart [partition UUID]
>> > +
>> > +            lists the partition(s) info
>> > +
>> > +        ping [partition ID]
>> > +
>> > +            sends a data pattern to the specified partition
>> > +
>> > +        devlist
>> > +
>> > +            displays information about the FF-A device/driver
>> > +
>> > +Description
>> > +-----------
>> > +
>> > +armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
>> > +
>> > +This provides a guidance to the client developers on how to call the FF-A bus interfaces.
>> > +
>> > +The command also allows to gather secure partitions information and ping these  partitions.
>> > +
>> > +The command is also helpful in testing the communication with secure partitions.
>> > +
>> > +Example
>> > +-------
>> > +
>> > +The following examples are run on Corstone-1000 platform with debug logs enabled.
>> > +
>> > +* ping
>> > +
>> > +::
>> > +
>> > +   corstone1000# armffa ping 0x8003
>> > +   SP response:
>> > +   [LSB]
>> > +   fffffffe
>> > +   0
>> > +   0
>> > +   0
>> > +   0
>> > +
>> > +* ping (failure case)
>> > +
>> > +::
>> > +
>> > +   corstone1000# armffa ping 0
>> > +   Sending direct request error (-22)
>> > +
>> > +* getpart
>> > +
>> > +::
>> > +
>> > +   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
>> > +   Preparing for checking FF-A partitions count
>> > +   Searching FF-A partitions using the provided UUID
>> > +   No FF-A partition found. Querying framework ...
>> > +   Reading FF-A partitions data from the RX buffer
>> > +   Number of FF-A partition(s) matching the UUID: 1
>> > +   Pre-allocating 1 partition(s) info structures
>> > +   Preparing for filling FF-A partitions info
>> > +   Searching FF-A partitions using the provided UUID
>> > +   FF-A partition ID 8003 matches the provided UUID
>> > +   Partition: id = 8003 , exec_ctxt 1 , properties 3
>> > +
>> > +* getpart (failure case)
>> > +
>> > +::
>> > +
>> > +   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221
>> > +   Preparing for checking FF-A partitions count
>> > +   Searching FF-A partitions using the provided UUID
>> > +   No FF-A partition found. Querying framework ...
>> > +   INVALID_PARAMETERS: Unrecognized UUID
>> > +   Failure in querying partitions count (error code: -22)
>> > +
>> > +* devlist
>> > +
>> > +::
>> > +
>> > +   corstone1000# armffa devlist
>> > +   device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98
>> > +
>> > +Configuration
>> > +-------------
>> > +
>> > +The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
>> > +
>> > +Return value
>> > +------------
>> > +
>> > +The return value $? is 0 (true) on success and a negative error code on failure.
>> 
>> CMD_RET_FAILURE results in $? being 1 (false). Did you actually see a
>> negative value?
>
>For armffa, the possible return codes are: CMD_RET_USAGE (-1), CMD_RET_FAILURE (1) and CMD_RET_SUCCESS (0)
>
>I suggest replacing the sentence with:
>
>The return value $? is 0 (true) on success, -1 on usage error and 1 (false) on FF-A related failures.

CMD_RET_USAGE results in $? =1.

>
>Cheers
>Abdellatif
>
>> 
>> Best regards
>> 
>> Heinrich
>> 
>> 
>> > diff --git a/doc/usage/index.rst b/doc/usage/index.rst
>> > index bc85e1d49a..df107fb710 100644
>> > --- a/doc/usage/index.rst
>> > +++ b/doc/usage/index.rst
>> > @@ -21,6 +21,7 @@ Shell commands
>> > 
>> >      cmd/acpi
>> >      cmd/addrmap
>> > +   cmd/armffa
>> >      cmd/askenv
>> >      cmd/base
>> >      cmd/bdinfo
>> > diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
>> > index 9200c8028b..a7d5392859 100644
>> > --- a/drivers/firmware/arm-ffa/Kconfig
>> > +++ b/drivers/firmware/arm-ffa/Kconfig
>> > @@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
>> >   	depends on DM && ARM64
>> >   	select ARM_SMCCC
>> >   	select ARM_SMCCC_FEATURES
>> > +	imply CMD_ARMFFA
>> >   	select LIB_UUID
>> >   	select DEVRES
>> >   	help
>> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 05/10] arm_ffa: introduce armffa command
  2023-04-12 20:00                                                                                                 ` Heinrich Schuchardt
@ 2023-04-13 10:15                                                                                                   ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-13 10:15 UTC (permalink / raw)
  To: Heinrich Schuchardt; +Cc: u-boot, nd

On Wed, Apr 12, 2023 at 10:00:38PM +0200, Heinrich Schuchardt wrote:
> 
> 
> Am 12. April 2023 17:53:23 MESZ schrieb Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>:
> >On Wed, Apr 12, 2023 at 04:02:43PM +0200, Heinrich Schuchardt wrote:
> >> On 4/12/23 11:42, Abdellatif El Khlifi wrote:
> >> > Provide armffa command showcasing the use of the U-Boot FF-A support
> >> > 
> >> > armffa is a command showcasing how to invoke FF-A operations.
> >> > This provides a guidance to the client developers on how to
> >> > call the FF-A bus interfaces. The command also allows to gather secure
> >> > partitions information and ping these  partitions. The command is also
> >> > helpful in testing the communication with secure partitions.
> >> > 
> >> > For more details please refer to the command documentation [1].
> >> > 
> >> > [1]: doc/usage/cmd/armffa.rst
> >> > 
> >> > 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>
> >> > Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
> >> > 
> >> > ---
> >> > Changelog:
> >> > ===============
> >> > 
> >> > v11:
> >> > 
> >> > * use U_BOOT_CMD_WITH_SUBCMDS
> >> > * address nits
> >> > 
> >> > v10:
> >> > 
> >> > * use the FF-A driver Uclass operations
> >> > * use uclass_first_device()
> >> > * address nits
> >> > 
> >> > v9:
> >> > 
> >> > * remove manual FF-A discovery and use DM
> >> > * use DM class APIs to probe and interact with the FF-A bus
> >> > * add doc/usage/cmd/armffa.rst
> >> > 
> >> > v8:
> >> > 
> >> > * update partition_info_get() second argument to be an SP count
> >> > * pass NULL device pointer to the FF-A bus discovery and operations
> >> > 
> >> > v7:
> >> > 
> >> > * adapt do_ffa_dev_list() following the recent update on
> >> >    uclass_first_device/uclass_next_device functions (they return void now)
> >> > * set armffa command to use 64-bit direct messaging
> >> > 
> >> > v4:
> >> > 
> >> > * remove pattern data in do_ffa_msg_send_direct_req
> >> > 
> >> > v3:
> >> > 
> >> > * use the new driver interfaces (partition_info_get, sync_send_receive)
> >> >    in armffa command
> >> > 
> >> > v2:
> >> > 
> >> > * replace use of ffa_helper_init_device function by
> >> >   ffa_helper_bus_discover
> >> > 
> >> > v1:
> >> > 
> >> > * introduce armffa command
> >> > 
> >> >   MAINTAINERS                      |   2 +
> >> >   cmd/Kconfig                      |  10 ++
> >> >   cmd/Makefile                     |   2 +
> >> >   cmd/armffa.c                     | 212 +++++++++++++++++++++++++++++++
> >> >   doc/arch/arm64.ffa.rst           |   7 +
> >> >   doc/usage/cmd/armffa.rst         | 105 +++++++++++++++
> >> >   doc/usage/index.rst              |   1 +
> >> >   drivers/firmware/arm-ffa/Kconfig |   1 +
> >> >   8 files changed, 340 insertions(+)
> >> >   create mode 100644 cmd/armffa.c
> >> >   create mode 100644 doc/usage/cmd/armffa.rst
> >> > 
> >> > diff --git a/MAINTAINERS b/MAINTAINERS
> >> > index 76f0f276ce..c64804ca2d 100644
> >> > --- a/MAINTAINERS
> >> > +++ b/MAINTAINERS
> >> > @@ -269,7 +269,9 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
> >> >   ARM FF-A
> >> >   M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >> >   S:	Maintained
> >> > +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
> >> > diff --git a/cmd/Kconfig b/cmd/Kconfig
> >> > index 8c9b430f99..4cb0b2c167 100644
> >> > --- a/cmd/Kconfig
> >> > +++ b/cmd/Kconfig
> >> > @@ -934,6 +934,16 @@ endmenu
> >> > 
> >> >   menu "Device access commands"
> >> > 
> >> > +config CMD_ARMFFA
> >> > +	bool "Arm FF-A test command"
> >> > +	depends on ARM_FFA_TRANSPORT
> >> > +	help
> >> > +	  Provides a test command for the FF-A support
> >> > +	  supported options:
> >> > +		- Listing the partition(s) info
> >> > +		- Sending a data pattern to the specified partition
> >> > +		- Displaying the arm_ffa device info
> >> > +
> >> >   config CMD_ARMFLASH
> >> >   	#depends on FLASH_CFI_DRIVER
> >> >   	bool "armflash"
> >> > diff --git a/cmd/Makefile b/cmd/Makefile
> >> > index e032091621..9130b9078d 100644
> >> > --- a/cmd/Makefile
> >> > +++ b/cmd/Makefile
> >> > @@ -12,6 +12,8 @@ obj-y += panic.o
> >> >   obj-y += version.o
> >> > 
> >> >   # command
> >> > +
> >> > +obj-$(CONFIG_CMD_ARMFFA) += armffa.o
> >> >   obj-$(CONFIG_CMD_ACPI) += acpi.o
> >> >   obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
> >> >   obj-$(CONFIG_CMD_AES) += aes.o
> >> > diff --git a/cmd/armffa.c b/cmd/armffa.c
> >> > new file mode 100644
> >> > index 0000000000..ab88412c7d
> >> > --- /dev/null
> >> > +++ b/cmd/armffa.c
> >> > @@ -0,0 +1,212 @@
> >> > +// 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 <command.h>
> >> > +#include <dm.h>
> >> > +#include <mapmem.h>
> >> > +#include <stdlib.h>
> >> > +#include <asm/io.h>
> >> > +
> >> > +/**
> >> > + * ffa_get_dev() - Return the FF-A device
> >> > + * @devp:	pointer to the FF-A device
> >> > + *
> >> > + * Search for the FF-A device.
> >> > + *
> >> > + * Return:
> >> > + * 0 on success. Otherwise, failure
> >> > + */
> >> > +int ffa_get_dev(struct udevice **devp)
> >> > +{
> >> > +	int ret;
> >> > +
> >> > +	ret = uclass_first_device_err(UCLASS_FFA, devp);
> >> > +	if (ret) {
> >> > +		log_err("Cannot find FF-A bus device\n");
> >> > +		return -ENODEV;
> >> > +	}
> >> > +
> >> > +	return 0;
> >> > +}
> >> > +
> >> > +/**
> >> > + * do_ffa_getpart() - implementation of the getpart subcommand
> >> > + * @cmdtp:		Command Table
> >> > + * @flag:		flags
> >> > + * @argc:		number of arguments
> >> > + * @argv:		arguments
> >> > + *
> >> > + * Query the secure partition information which the UUID is provided
> >> > + * as an argument. The function uses the arm_ffa driver
> >> > + * partition_info_get operation which implements FFA_PARTITION_INFO_GET
> >> > + * ABI to retrieve the data. The input UUID string is expected to be in big
> >> > + * endian format.
> >> > + *
> >> > + * Return:
> >> > + *
> >> > + * CMD_RET_SUCCESS: on success, otherwise failure
> >> > + */
> >> > +static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
> >> > +			  char *const argv[])
> >> > +{
> >> > +	u32 count = 0;
> >> > +	int ret;
> >> > +	struct ffa_partition_info *parts_info;
> >> > +	u32 i;
> >> > +	struct udevice *dev;
> >> > +
> >> > +	ret = ffa_get_dev(&dev);
> >> > +	if (ret)
> >> > +		return CMD_RET_FAILURE;
> >> > +
> >> > +	/* Mode 1: getting the number of secure partitions */
> >> > +	ret = ffa_partition_info_get(dev, argv[1], &count, NULL);
> >> > +	if (ret) {
> >> > +		log_err("Failure in querying partitions count (error code: %d)\n", ret);
> >> > +		return CMD_RET_FAILURE;
> >> > +	}
> >> > +
> >> > +	if (!count) {
> >> > +		log_info("No secure partition found\n");
> >> > +		return CMD_RET_FAILURE;
> >> > +	}
> >> > +
> >> > +	/*
> >> > +	 * Pre-allocate a buffer to be filled by the driver
> >> > +	 * with ffa_partition_info structs
> >> > +	 */
> >> > +
> >> > +	log_info("Pre-allocating %d partition(s) info structures\n", count);
> >> > +
> >> > +	parts_info = calloc(count, sizeof(struct ffa_partition_info));
> >> > +	if (!parts_info)
> >> > +		return CMD_RET_FAILURE;
> >> > +
> >> > +	/* Ask the driver to fill the buffer with the SPs info */
> >> > +
> >> > +	ret = ffa_partition_info_get(dev, argv[1], &count, parts_info);
> >> > +	if (ret) {
> >> > +		log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
> >> > +		free(parts_info);
> >> > +		return CMD_RET_FAILURE;
> >> > +	}
> >> > +
> >> > +	/* SPs found , show the partition information */
> >> > +	for (i = 0; i < count ; i++) {
> >> > +		log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
> >> > +			 parts_info[i].id,
> >> > +			 parts_info[i].exec_ctxt,
> >> > +			 parts_info[i].properties);
> >> > +	}
> >> > +
> >> > +	free(parts_info);
> >> > +
> >> > +	return CMD_RET_SUCCESS;
> >> > +}
> >> > +
> >> > +/**
> >> > + * do_ffa_ping() - implementation of the ping subcommand
> >> > + * @cmdtp:		Command Table
> >> > + * @flag:		flags
> >> > + * @argc:		number of arguments
> >> > + * @argv:		arguments
> >> > + *
> >> > + * Send data to the secure partition which the ID is provided
> >> > + * as an argument. Use the arm_ffa driver sync_send_receive operation
> >> > + * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
> >> > + *
> >> > + * Return:
> >> > + *
> >> > + * CMD_RET_SUCCESS: on success, otherwise failure
> >> > + */
> >> > +int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> >> > +{
> >> > +	struct ffa_send_direct_data msg = {
> >> > +			.data0 = 0xaaaaaaaa,
> >> > +			.data1 = 0xbbbbbbbb,
> >> > +			.data2 = 0xcccccccc,
> >> > +			.data3 = 0xdddddddd,
> >> > +			.data4 = 0xeeeeeeee,
> >> > +	};
> >> > +	u16 part_id;
> >> > +	int ret;
> >> > +	struct udevice *dev;
> >> > +
> >> > +	errno = 0;
> >> > +	part_id = strtoul(argv[1], NULL, 16);
> >> > +
> >> > +	if (errno) {
> >> > +		log_err("Invalid partition ID\n");
> >> > +		return CMD_RET_USAGE;
> >> > +	}
> >> > +
> >> > +	ret = ffa_get_dev(&dev);
> >> > +	if (ret)
> >> > +		return CMD_RET_FAILURE;
> >> > +
> >> > +	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
> >> > +	if (!ret) {
> >> > +		u8 cnt;
> >> > +
> >> > +		log_info("SP response:\n[LSB]\n");
> >> > +		for (cnt = 0;
> >> > +		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
> >> > +		     cnt++)
> >> > +			log_info("%llx\n", ((u64 *)&msg)[cnt]);
> >> > +		return CMD_RET_SUCCESS;
> >> > +	}
> >> > +
> >> > +	log_err("Sending direct request error (%d)\n", ret);
> >> > +	return CMD_RET_FAILURE;
> >> > +}
> >> > +
> >> > +/**
> >> > + *do_ffa_devlist() - implementation of the devlist subcommand
> >> > + * @cmdtp: [in]		Command Table
> >> > + * @flag:		flags
> >> > + * @argc:		number of arguments
> >> > + * @argv:		arguments
> >> > + *
> >> > + * Query the device belonging to the UCLASS_FFA
> >> > + * class.
> >> > + *
> >> > + * Return:
> >> > + *
> >> > + * CMD_RET_SUCCESS: on success, otherwise failure
> >> > + */
> >> > +int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> >> > +{
> >> > +	struct udevice *dev;
> >> > +	int ret;
> >> > +
> >> > +	ret = ffa_get_dev(&dev);
> >> > +	if (ret)
> >> > +		return CMD_RET_FAILURE;
> >> > +
> >> > +	log_info("device name %s, dev %p, driver name %s, ops %p\n",
> >> > +		 dev->name,
> >> > +		(void *)map_to_sysmem(dev),
> >> > +		 dev->driver->name,
> >> > +		 (void *)map_to_sysmem(dev->driver->ops));
> >> > +
> >> > +	return CMD_RET_SUCCESS;
> >> > +}
> >> > +
> >> > +static char armffa_help_text[] =
> >> > +	"getpart <partition UUID>\n"
> >> > +	"       - lists the partition(s) info\n"
> >> > +	"ping <partition ID>\n"
> >> > +	"       - sends a data pattern to the specified partition\n"
> >> > +	"devlist\n"
> >> > +	"       - displays information about the FF-A device/driver\n";
> >> > +
> >> > +U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
> >> > +			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
> >> > +			U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping),
> >> > +			U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist));
> >> > diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> >> > index 466e77e3cd..ed7240aef7 100644
> >> > --- a/doc/arch/arm64.ffa.rst
> >> > +++ b/doc/arch/arm64.ffa.rst
> >> > @@ -216,6 +216,13 @@ The following features are provided:
> >> > 
> >> >   - FF-A bus can be compiled and used without EFI
> >> > 
> >> > +The armffa command
> >> > +-----------------------------------
> >> > +
> >> > +armffa is an implementation defined command showcasing how to use the FF-A bus and how to invoke the driver operations.
> >> > +
> >> > +Please refer the command documentation at doc/usage/cmd/armffa.rst
> >> > +
> >> >   Example of boot logs with FF-A enabled
> >> >   --------------------------------------
> >> > 
> >> > diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
> >> > new file mode 100644
> >> > index 0000000000..e73d03ae51
> >> > --- /dev/null
> >> > +++ b/doc/usage/cmd/armffa.rst
> >> > @@ -0,0 +1,105 @@
> >> > +.. SPDX-License-Identifier: GPL-2.0+:
> >> > +
> >> > +armffa command
> >> > +==============
> >> > +
> >> > +Synopsis
> >> > +--------
> >> > +
> >> > +::
> >> > +
> >> > +   armffa [sub-command] [arguments]
> >> > +
> >> > +   sub-commands:
> >> > +
> >> > +        getpart [partition UUID]
> >> > +
> >> > +            lists the partition(s) info
> >> > +
> >> > +        ping [partition ID]
> >> > +
> >> > +            sends a data pattern to the specified partition
> >> > +
> >> > +        devlist
> >> > +
> >> > +            displays information about the FF-A device/driver
> >> > +
> >> > +Description
> >> > +-----------
> >> > +
> >> > +armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
> >> > +
> >> > +This provides a guidance to the client developers on how to call the FF-A bus interfaces.
> >> > +
> >> > +The command also allows to gather secure partitions information and ping these  partitions.
> >> > +
> >> > +The command is also helpful in testing the communication with secure partitions.
> >> > +
> >> > +Example
> >> > +-------
> >> > +
> >> > +The following examples are run on Corstone-1000 platform with debug logs enabled.
> >> > +
> >> > +* ping
> >> > +
> >> > +::
> >> > +
> >> > +   corstone1000# armffa ping 0x8003
> >> > +   SP response:
> >> > +   [LSB]
> >> > +   fffffffe
> >> > +   0
> >> > +   0
> >> > +   0
> >> > +   0
> >> > +
> >> > +* ping (failure case)
> >> > +
> >> > +::
> >> > +
> >> > +   corstone1000# armffa ping 0
> >> > +   Sending direct request error (-22)
> >> > +
> >> > +* getpart
> >> > +
> >> > +::
> >> > +
> >> > +   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
> >> > +   Preparing for checking FF-A partitions count
> >> > +   Searching FF-A partitions using the provided UUID
> >> > +   No FF-A partition found. Querying framework ...
> >> > +   Reading FF-A partitions data from the RX buffer
> >> > +   Number of FF-A partition(s) matching the UUID: 1
> >> > +   Pre-allocating 1 partition(s) info structures
> >> > +   Preparing for filling FF-A partitions info
> >> > +   Searching FF-A partitions using the provided UUID
> >> > +   FF-A partition ID 8003 matches the provided UUID
> >> > +   Partition: id = 8003 , exec_ctxt 1 , properties 3
> >> > +
> >> > +* getpart (failure case)
> >> > +
> >> > +::
> >> > +
> >> > +   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221
> >> > +   Preparing for checking FF-A partitions count
> >> > +   Searching FF-A partitions using the provided UUID
> >> > +   No FF-A partition found. Querying framework ...
> >> > +   INVALID_PARAMETERS: Unrecognized UUID
> >> > +   Failure in querying partitions count (error code: -22)
> >> > +
> >> > +* devlist
> >> > +
> >> > +::
> >> > +
> >> > +   corstone1000# armffa devlist
> >> > +   device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98
> >> > +
> >> > +Configuration
> >> > +-------------
> >> > +
> >> > +The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
> >> > +
> >> > +Return value
> >> > +------------
> >> > +
> >> > +The return value $? is 0 (true) on success and a negative error code on failure.
> >> 
> >> CMD_RET_FAILURE results in $? being 1 (false). Did you actually see a
> >> negative value?
> >
> >For armffa, the possible return codes are: CMD_RET_USAGE (-1), CMD_RET_FAILURE (1) and CMD_RET_SUCCESS (0)
> >
> >I suggest replacing the sentence with:
> >
> >The return value $? is 0 (true) on success, -1 on usage error and 1 (false) on FF-A related failures.
> 
> CMD_RET_USAGE results in $? =1.

Ok, I'll take that into account. Thanks.

> 
> >
> >Cheers
> >Abdellatif
> >
> >> 
> >> Best regards
> >> 
> >> Heinrich
> >> 
> >> 
> >> > diff --git a/doc/usage/index.rst b/doc/usage/index.rst
> >> > index bc85e1d49a..df107fb710 100644
> >> > --- a/doc/usage/index.rst
> >> > +++ b/doc/usage/index.rst
> >> > @@ -21,6 +21,7 @@ Shell commands
> >> > 
> >> >      cmd/acpi
> >> >      cmd/addrmap
> >> > +   cmd/armffa
> >> >      cmd/askenv
> >> >      cmd/base
> >> >      cmd/bdinfo
> >> > diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> >> > index 9200c8028b..a7d5392859 100644
> >> > --- a/drivers/firmware/arm-ffa/Kconfig
> >> > +++ b/drivers/firmware/arm-ffa/Kconfig
> >> > @@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
> >> >   	depends on DM && ARM64
> >> >   	select ARM_SMCCC
> >> >   	select ARM_SMCCC_FEATURES
> >> > +	imply CMD_ARMFFA
> >> >   	select LIB_UUID
> >> >   	select DEVRES
> >> >   	help
> >> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 00/10] introduce Arm FF-A support
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                             ` (9 preceding siblings ...)
  2023-04-12  9:42                                                                                           ` [PATCH v11 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
@ 2023-04-17 16:02                                                                                           ` Abdellatif El Khlifi
  2023-04-18 16:48                                                                                             ` Simon Glass
  2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
  11 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-04-17 16:02 UTC (permalink / raw)
  To: sjg; +Cc: nd, u-boot

Hi Simon,

> Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> 
> FF-A describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World. These interfaces enable a pair of
> software sandboxes to communicate with each other. A sandbox aka partition could
> be a VM in the Normal or Secure world, an application in S-EL0, or a
> Trusted OS in S-EL1.
> 
> FF-A is a discoverable bus and similar to architecture features.
> FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> by the PSCI driver.
> 
>    => dm tree
> 
>     Class     Index  Probed  Driver                Name
>    -----------------------------------------------------------
>    ...
>     firmware      0  [ + ]   psci                      |-- psci
>     ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
>    ...
> 
> Clients are able to probe then use the FF-A bus by calling the DM class
> searching APIs (e.g: uclass_get_device_by_name).
> 
> This implementation of the specification provides support for Aarch64.
> 
> The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> 
>     - Discover the presence of secure partitions (SPs) of interest
>     - Access an SP's service through communication protocols
>       e.g. EFI MM communication protocol
> 
> The FF-A support provides the following features:
> 
>     - Being generic by design and can be used by any Arm 64-bit platform
>     - A Uclass driver providing generic FF-A methods and driver operations
>     - An Arm FF-A device driver
>     - FF-A support can be compiled and used without EFI
>     - Support for SMCCCv1.2 x0-x17 registers
>     - Support for SMC32 calling convention
>     - Support for 32-bit and 64-bit FF-A direct messaging
>     - A new command called armffa is provided as an example of how to access the
>       FF-A bus
>     - Support for FF-A MM communication (compatible with EFI boot time)
>     - Enabling FF-A and MM communication in Corstone1000 platform as a use case
>     - A sandbox emulator for Arm FF-A
>     - An FF-A sandbox device driver
>     - Sandbox FF-A test cases
> 
> For more details about the FF-A support please refer to [B] and refer to [C] for
> how to use the armffa command.
> 
> Please find at [D] an example of the expected boot logs when enabling
> FF-A support for a platform. In this example the platform is
> Corstone1000. But it can be any Arm 64-bit platform.
> 
> Changelog of the major changes:
> ===========================
> 
> v11:
> 
> * move ffa_try_discovery() from the uclass to the Arm FF-A driver
> * rename ffa_try_discovery() to arm_ffa_discover()
> * add arm_ prefix to the Arm FF-A driver functions
> * use U_BOOT_CMD_WITH_SUBCMDS for armffa command
> * store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
> * set the emulator as parent of the sandbox FF-A device
> * rename select_ffa_mm_comms() to select_mm_comms()
> * improve the logic of MM transport selection in mm_communicate()
> * use ut_asserteq_mem() in uuid_str_to_le_bin test case
> * address nits

A gentle reminder for reviewing the v11 changes please.
I already put you in CC :)

Thank you in advance.

Cheers,
Abdellatif

> 
> v10: [10]
> 
> * provide the FF-A driver operations through the Uclass (arm-ffa-uclass.c)
> * move the generic FF-A methods to the Uclass
> * keep Arm specific methods in the Arm driver (arm-ffa.c renamed from core.c)
> * split the FF-A sandbox support into an emulator (ffa-emul-uclass.c) and a driver (sandbox_ffa.c)
> * use the FF-A driver Uclass operations by clients (armffa command, tests, MM comms)
> * use uclass_first_device to search and probe the FF-A device (whether it is on Arm or on sandbox)
> * address nits
> 
> v9: [9]
> 
> * integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
> * align FF-A sandbox driver with FF-A discovery through DM
> * use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
> * add documentation for the armffa command: doc/usage/cmd/armffa.rst
> * introduce testcase for uuid_str_to_le_bin
> 
> v8: [8]
> 
> * pass the FF-A bus device to the bus operations
> * isolate the compilation choices between FF-A and OP-TEE
> * drop OP-TEE configs from Corstone-1000 defconfig
> * make ffa_get_partitions_info() second argument to be an SP count in both
>   modes
> 
> v7: [7]
> 
> * add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
> * set the MM door bell event to use 64-bit direct messaging
> * issue a compile time error when one of these macros are not found :
>   FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
> * make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
>   by using same APIs
> 
> v6: [6]
> 
> * remove clearing x0-x17 registers after SMC calls
> * drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
> * drop discovery from initcalls (discovery will be on demand by FF-A users)
> * add FF-A runtime discovery at MM communication level
> * update the documentation and move it to doc/arch/arm64.ffa.rst
> 
> v5: [5]
> 
> * move changelogs in each commit to the changes section
> 
> v4: [4]
> 
> * add FF-A support README (doc/README.ffa.drv)
> * improving error handling by mapping the FF-A errors to standard errors
>   and logs
> * replacing panics with an error log
> * align sandbox driver and tests with the new FF-A driver interfaces
>  and new way of error handling
> * use the new FF-A driver interfaces for MM communication
> * discover MM partitions at runtime
> * copy FF-A driver private data to EFI runtime section at
>   ExitBootServices()
> * moving the FF-A driver work to drivers/firmware/arm-ffa
> * improving features discovery in FFA_FEATURES
> * add remove/unbind functions to the FF-A core device
> * improve how the driver behaves when bus discovery is done more than
>   once
> * move clearing x0-x17 registers code into a new macro like done in
>    the linux kernel
> * enable EFI MM communication for the Corstone1000 platform
> 
> v3: [3]
> 
> * port x0-x17 registers support from linux kernel as defined by
>    SMCCCv1.2
> * align the interfaces of the u-boot FF-A driver with those in the linux
>    FF-A driver
> * remove the FF-A helper layer
> * make the u-boot FF-A driver independent from EFI
> * provide an optional config that enables copying the driver data to
>    EFI runtime section at ExitBootServices service
> * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
> * update armffa command with the new driver interfaces
> 
> v2  [2]:
> 
> * make FF-A bus discoverable using device_{bind, probe} APIs
> * remove device tree support
> 
> v1  [1]:
> 
> * introduce FF-A bus driver with device tree support
> * introduce armffa command
> * introduce FF-A Sandbox driver
> * add FF-A Sandbox test cases
> * introduce FF-A MM communication
> 
> Cheers,
> Abdellatif
> 
> List of previous patches:
> 
> [1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
> [2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
> [3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
> [4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
> [5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
> [6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
> [7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
> [8]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
> [9]: https://lore.kernel.org/all/20230310141016.137986-1-abdellatif.elkhlifi@arm.com/
> [10]: https://lore.kernel.org/all/20230328161157.219375-1-abdellatif.elkhlifi@arm.com/
> 
> More details:
> 
> [A]: https://developer.arm.com/documentation/den0077/latest/
> [B]: doc/arch/arm64.ffa.rst
> [C]: doc/usage/cmd/armffa.rst
> [D]: example of boot logs when enabling FF-A
> 
> ```
>    U-Boot 2023.01 (Mar 27 2023 - 13:48:33 +0000) corstone1000 aarch64
> 
>    DRAM:  2 GiB
>    Arm FF-A framework discovery
>    Using Arm SMC for FF-A conduit
>    FF-A driver 1.0
>    FF-A framework 1.0
>    FF-A versions are compatible
>    ...
>    Hit any key to stop autoboot:  0
>    Loading kernel from 0x083EE000 to memory ...
>    ...
>    FF-A endpoint ID is 0
>    Using 1 4KB page(s) for FF-A RX/TX buffers size
>    FF-A RX buffer at virtual address 00000000fdf4f000
>    FF-A TX buffer at virtual address 00000000fdf51000
>    FF-A RX/TX buffers mapped
>    Reading FF-A partitions data from the RX buffer
>    FF-A partition ID 8001 : info cached
>    FF-A partition ID 8002 : info cached
>    FF-A partition ID 8003 : info cached
>    3 FF-A partition(s) found and cached
>    Preparing for checking FF-A partitions count
>    Searching FF-A partitions using the provided UUID
>    No FF-A partition found. Querying framework ...
>    Reading FF-A partitions data from the RX buffer
>    Number of FF-A partition(s) matching the UUID: 1
>    EFI: Pre-allocating 1 partition(s) info structures
>    Preparing for filling FF-A partitions info
>    Searching FF-A partitions using the provided UUID
>    FF-A partition ID 8003 matches the provided UUID
>    EFI: MM partition ID 0x8003
>    EFI: Corstone1000: Capsule shared buffer at 0x80000000 , size 8192 pages
>    Booting /MemoryMapped(0x0,0x88200000,0xf00000)
>    EFI stub: Booting Linux Kernel...
>    EFI stub: Using DTB from configuration table
>    EFI stub: Exiting boot services...
>    unmapping FF-A RX/TX buffers
>    Freeing FF-A RX/TX buffers
>    Booting Linux on physical CPU 0x0000000000 [0x411fd040]
>    Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
>    Machine model: ARM Corstone1000 FPGA MPS3 board
> ```
> 
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Rob Herring <robh@kernel.org>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Cc: Jens Wiklander <jens.wiklander@linaro.org>
> Cc: Achin Gupta <achin.gupta@arm.com>
> Cc: Drew Reed <Drew.Reed@arm.com>
> Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>
> 
> Abdellatif El Khlifi (10):
>   arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
>   lib: uuid: introduce uuid_str_to_le_bin function
>   lib: uuid: introduce testcase for uuid_str_to_le_bin
>   arm_ffa: introduce Arm FF-A support
>   arm_ffa: introduce armffa command
>   arm_ffa: introduce sandbox FF-A support
>   arm_ffa: introduce sandbox test cases for UCLASS_FFA
>   arm_ffa: introduce armffa command Sandbox test
>   arm_ffa: efi: introduce FF-A MM communication
>   arm_ffa: efi: corstone1000: enable MM communication
> 
>  MAINTAINERS                                   |   18 +
>  arch/arm/cpu/armv8/smccc-call.S               |   57 +-
>  arch/arm/lib/asm-offsets.c                    |   16 +
>  arch/sandbox/dts/sandbox.dtsi                 |    8 +
>  arch/sandbox/dts/test.dts                     |    8 +
>  arch/sandbox/include/asm/sandbox_arm_ffa.h    |   72 ++
>  .../include/asm/sandbox_arm_ffa_priv.h        |  133 ++
>  cmd/Kconfig                                   |   10 +
>  cmd/Makefile                                  |    2 +
>  cmd/armffa.c                                  |  212 +++
>  configs/corstone1000_defconfig                |    2 +
>  configs/sandbox64_defconfig                   |    1 +
>  configs/sandbox_defconfig                     |    1 +
>  doc/arch/arm64.ffa.rst                        |  294 +++++
>  doc/arch/index.rst                            |    1 +
>  doc/arch/sandbox/sandbox.rst                  |    1 +
>  doc/usage/cmd/armffa.rst                      |  105 ++
>  doc/usage/index.rst                           |    1 +
>  drivers/Makefile                              |    1 +
>  drivers/firmware/Kconfig                      |    1 +
>  drivers/firmware/arm-ffa/Kconfig              |   42 +
>  drivers/firmware/arm-ffa/Makefile             |   16 +
>  drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1143 +++++++++++++++++
>  drivers/firmware/arm-ffa/arm-ffa.c            |  127 ++
>  drivers/firmware/arm-ffa/ffa-emul-uclass.c    |  738 +++++++++++
>  drivers/firmware/arm-ffa/sandbox_ffa.c        |  119 ++
>  include/arm_ffa.h                             |  217 ++++
>  include/arm_ffa_priv.h                        |  271 ++++
>  include/configs/corstone1000.h                |   15 +-
>  include/dm/uclass-id.h                        |    7 +
>  include/linux/arm-smccc.h                     |   45 +
>  include/mm_communication.h                    |   13 +
>  include/uuid.h                                |   15 +
>  lib/efi_loader/Kconfig                        |   14 +-
>  lib/efi_loader/efi_variable_tee.c             |  312 ++++-
>  lib/uuid.c                                    |   48 +
>  test/cmd/Makefile                             |    2 +
>  test/cmd/armffa.c                             |   39 +
>  test/dm/Makefile                              |    2 +
>  test/dm/ffa.c                                 |  258 ++++
>  test/lib/Makefile                             |    1 +
>  test/lib/uuid.c                               |   41 +
>  42 files changed, 4420 insertions(+), 9 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 cmd/armffa.c
>  create mode 100644 doc/arch/arm64.ffa.rst
>  create mode 100644 doc/usage/cmd/armffa.rst
>  create mode 100644 drivers/firmware/arm-ffa/Kconfig
>  create mode 100644 drivers/firmware/arm-ffa/Makefile
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
>  create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
>  create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
>  create mode 100644 include/arm_ffa.h
>  create mode 100644 include/arm_ffa_priv.h
>  create mode 100644 test/cmd/armffa.c
>  create mode 100644 test/dm/ffa.c
>  create mode 100644 test/lib/uuid.c
> 
> -- 
> 2.25.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 00/10] introduce Arm FF-A support
  2023-04-17 16:02                                                                                           ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-04-18 16:48                                                                                             ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-04-18 16:48 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: nd, u-boot

Hi Abdellatif,

On Mon, 17 Apr 2023 at 10:03, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Hi Simon,
>
> > Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> >
> > FF-A describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World. These interfaces enable a pair of
> > software sandboxes to communicate with each other. A sandbox aka partition could
> > be a VM in the Normal or Secure world, an application in S-EL0, or a
> > Trusted OS in S-EL1.
> >
> > FF-A is a discoverable bus and similar to architecture features.
> > FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> > by the PSCI driver.
> >
> >    => dm tree
> >
> >     Class     Index  Probed  Driver                Name
> >    -----------------------------------------------------------
> >    ...
> >     firmware      0  [ + ]   psci                      |-- psci
> >     ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
> >    ...
> >
> > Clients are able to probe then use the FF-A bus by calling the DM class
> > searching APIs (e.g: uclass_get_device_by_name).
> >
> > This implementation of the specification provides support for Aarch64.
> >
> > The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> >
> >     - Discover the presence of secure partitions (SPs) of interest
> >     - Access an SP's service through communication protocols
> >       e.g. EFI MM communication protocol
> >
> > The FF-A support provides the following features:
> >
> >     - Being generic by design and can be used by any Arm 64-bit platform
> >     - A Uclass driver providing generic FF-A methods and driver operations
> >     - An Arm FF-A device driver
> >     - FF-A support can be compiled and used without EFI
> >     - Support for SMCCCv1.2 x0-x17 registers
> >     - Support for SMC32 calling convention
> >     - Support for 32-bit and 64-bit FF-A direct messaging
> >     - A new command called armffa is provided as an example of how to access the
> >       FF-A bus
> >     - Support for FF-A MM communication (compatible with EFI boot time)
> >     - Enabling FF-A and MM communication in Corstone1000 platform as a use case
> >     - A sandbox emulator for Arm FF-A
> >     - An FF-A sandbox device driver
> >     - Sandbox FF-A test cases
> >
> > For more details about the FF-A support please refer to [B] and refer to [C] for
> > how to use the armffa command.
> >
> > Please find at [D] an example of the expected boot logs when enabling
> > FF-A support for a platform. In this example the platform is
> > Corstone1000. But it can be any Arm 64-bit platform.
> >
> > Changelog of the major changes:
> > ===========================
> >
> > v11:
> >
> > * move ffa_try_discovery() from the uclass to the Arm FF-A driver
> > * rename ffa_try_discovery() to arm_ffa_discover()
> > * add arm_ prefix to the Arm FF-A driver functions
> > * use U_BOOT_CMD_WITH_SUBCMDS for armffa command
> > * store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
> > * set the emulator as parent of the sandbox FF-A device
> > * rename select_ffa_mm_comms() to select_mm_comms()
> > * improve the logic of MM transport selection in mm_communicate()
> > * use ut_asserteq_mem() in uuid_str_to_le_bin test case
> > * address nits
>
> A gentle reminder for reviewing the v11 changes please.
> I already put you in CC :)
>
> Thank you in advance.

Yes I have started looking at it. Should be by Monday.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-04-12  9:42                                                                                           ` [PATCH v11 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-04-19  1:46                                                                                             ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-04-19  1:46 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, trini, u-boot, xueliang.zhong

On Wed, 12 Apr 2023 at 03:43, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> provide a test case
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Cc: Simon Glass <sjg@chromium.org>
>
> ---
> Changelog:
> ===============
>
> v11:
>
> * use ut_asserteq_mem()
>
>  MAINTAINERS       |  5 +++++
>  test/lib/Makefile |  1 +
>  test/lib/uuid.c   | 41 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 47 insertions(+)
>  create mode 100644 test/lib/uuid.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d2e245e5e9..086e4cb3df 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1607,3 +1607,8 @@ S:        Maintained
>  F:     arch/arm/dts/ls1021a-twr-u-boot.dtsi
>  F:     drivers/crypto/fsl/
>  F:     include/fsl_sec.h
> +
> +UUID testing
> +M:     Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +S:     Maintained
> +F:     test/lib/uuid.c
> diff --git a/test/lib/Makefile b/test/lib/Makefile
> index e0bd9e04e8..e75a263e6a 100644
> --- a/test/lib/Makefile
> +++ b/test/lib/Makefile
> @@ -22,6 +22,7 @@ obj-$(CONFIG_AES) += test_aes.o
>  obj-$(CONFIG_GETOPT) += getopt.o
>  obj-$(CONFIG_CRC8) += test_crc8.o
>  obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o
> +obj-$(CONFIG_LIB_UUID) += uuid.o
>  else
>  obj-$(CONFIG_SANDBOX) += kconfig_spl.o
>  endif
> diff --git a/test/lib/uuid.c b/test/lib/uuid.c
> new file mode 100644
> index 0000000000..e24331a136
> --- /dev/null
> +++ b/test/lib/uuid.c
> @@ -0,0 +1,41 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Functional tests for UCLASS_FFA  class
> + *
> + * 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 <uuid.h>
> +#include <test/lib.h>
> +#include <test/test.h>
> +#include <test/ut.h>
> +
> +/* test UUID */
> +#define TEST_SVC_UUID  "ed32d533-4209-99e6-2d72-cdd998a79cc0"
> +
> +#define UUID_SIZE 16
> +
> +/* The UUID binary data (little-endian format) */
> +static const u8 ref_uuid_bin[UUID_SIZE] = {
> +       0x33, 0xd5, 0x32, 0xed,
> +       0x09, 0x42, 0xe6, 0x99,
> +       0x72, 0x2d, 0xc0, 0x9c,
> +       0xa7, 0x98, 0xd9, 0xcd
> +};
> +
> +static int lib_test_uuid_to_le(struct unit_test_state *uts)
> +{
> +       const char *uuid_str = TEST_SVC_UUID;
> +       u8 ret_uuid_bin[UUID_SIZE] = {0};
> +
> +       ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin));
> +       ut_asserteq_mem(ref_uuid_bin, ret_uuid_bin, UUID_SIZE);
> +
> +       return 0;
> +}
> +
> +LIB_TEST(lib_test_uuid_to_le, 0);
> --
> 2.25.1
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-04-12  9:42                                                                                           ` [PATCH v11 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-04-19  1:49                                                                                             ` Simon Glass
  2023-05-12 12:12                                                                                               ` Abdellatif El Khlifi
  2023-04-21  8:10                                                                                             ` Ilias Apalodimas
  1 sibling, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-04-19  1:49 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, trini, u-boot, xueliang.zhong, Gowtham Suresh Kumar

Hi Abdellatif,

On Wed, 12 Apr 2023 at 03:43, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add MM communication support using FF-A transport
>
> This feature allows accessing MM partitions services through
> EFI MM communication protocol. MM partitions such as StandAlonneMM
> or smm-gateway secure partitions which reside in secure world.
>
> An MM shared buffer and a door bell event are used to exchange
> the data.
>
> The data is used by EFI services such as GetVariable()/SetVariable()
> and copied from the communication buffer to the MM shared buffer.
>
> The secure partition is notified about availability of data in the
> MM shared buffer by an FF-A message (door bell).
>
> On such event, MM SP can read the data and updates the MM shared
> buffer with the response data.
>
> The response data is copied back to the communication buffer and
> consumed by the EFI subsystem.
>
> MM communication protocol supports FF-A 64-bit direct messaging.
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>
>
> ---
> Changelog:
> ===============
>
> v11:
>
> * rename select_ffa_mm_comms() to select_mm_comms()
> * improve the logic of MM transport selection in mm_communicate()
> * addressing nits
>
> v10:
>
> * use the FF-A driver Uclass operations
> * use uclass_first_device()
> * addressing nits
>
> v9: align how FF-A is used with FF-A discovery through DM
>
> v8:
>
> * isolate the compilation choices between FF-A and OP-TEE
> * update partition_info_get() second argument to be an SP count
> * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7:
>
> * set the MM door bell event to use 64-bit direct messaging
> * issue a compile time error when one of these macros are not found :
>   FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
> * make mm_sp_svc_uuid static
> * replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
> * improve use of unmap_sysmem() in ffa_mm_communicate()
>
> v6:
>
> * add FF-A runtime discovery at MM communication level
> * drop EFI runtime support for FF-A MM communication
> * revert the changes in include/mm_communication.h for
>   efi_mm_communicate_header and smm_variable_access structures
>
> v4:
>
> * use the new FF-A driver interfaces
> * discover MM partitions at runtime
> * copy FF-A driver private data to EFI runtime section at
>   ExitBootServices()
> * drop use of FFA_ERR_STAT_SUCCESS error code
> * replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
>   in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
> * revert the error log in mm_communicate() in case of failure
> * remove packed attribute from efi_mm_communicate_header and
>   smm_variable_communicate_header
>
> v2:
>
> * set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings
>
> v1:
>
> * introduce FF-A MM communication
>
>  include/mm_communication.h        |  13 ++
>  lib/efi_loader/Kconfig            |  14 +-
>  lib/efi_loader/efi_variable_tee.c | 312 +++++++++++++++++++++++++++++-
>  3 files changed, 333 insertions(+), 6 deletions(-)
>
> diff --git a/include/mm_communication.h b/include/mm_communication.h
> index e65fbde60d..f17847583b 100644
> --- a/include/mm_communication.h
> +++ b/include/mm_communication.h
> @@ -6,6 +6,9 @@
>   *  Copyright (c) 2017, Intel Corporation. All rights reserved.
>   *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
>   *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
> + *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *    Authors:
> + *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>
>  #ifndef _MM_COMMUNICATION_H_
> @@ -13,6 +16,9 @@
>
>  #include <part_efi.h>
>
> +/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
> +#define MM_SP_UUID     "33d532ed-e699-0942-c09c-a798d9cd722d"
> +
>  /*
>   * Interface to the pseudo Trusted Application (TA), which provides a
>   * communication channel with the Standalone MM (Management Mode)
> @@ -248,4 +254,11 @@ struct smm_variable_var_check_property {
>         u16                       name[];
>  };
>
> +/* supported MM transports */
> +enum mm_comms_select {
> +       MM_COMMS_UNDEFINED,
> +       MM_COMMS_FFA,
> +       MM_COMMS_OPTEE
> +};
> +
>  #endif /* _MM_COMMUNICATION_H_ */
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index c5835e6ef6..08a6b84101 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
>           stored as file /ubootefi.var on the EFI system partition.
>
>  config EFI_MM_COMM_TEE
> -       bool "UEFI variables storage service via OP-TEE"
> -       depends on OPTEE
> +       bool "UEFI variables storage service via the trusted world"
> +       depends on OPTEE || ARM_FFA_TRANSPORT
>         help
> +         Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
> +         When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> +         When using the u-boot FF-A  driver any MM SP is supported.
> +
>           If OP-TEE is present and running StandAloneMM, dispatch all UEFI
>           variable related operations to that. The application will verify,
>           authenticate and store the variables on an RPMB.
>
> +         When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> +         operations to the MM SP running in the secure world.
> +         A door bell mechanism is used to notify the SP when there is data in the shared
> +         MM buffer. The data is copied by u-boot to the shared buffer before issuing
> +         the door bell event.
> +
>  config EFI_VARIABLE_NO_STORE
>         bool "Don't persist non-volatile UEFI variables"
>         help
> diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> index dfef18435d..a6ec126db5 100644
> --- a/lib/efi_loader/efi_variable_tee.c
> +++ b/lib/efi_loader/efi_variable_tee.c
> @@ -4,9 +4,14 @@
>   *
>   *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
>   *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
> + *  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 <efi.h>
>  #include <efi_api.h>
>  #include <efi_loader.h>
> @@ -15,6 +20,36 @@
>  #include <malloc.h>
>  #include <mm_communication.h>
>
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +
> +#include <arm_ffa.h>
> +#include <cpu_func.h>
> +#include <mapmem.h>
> +
> +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_SIZE 0
> +#endif
> +
> +#ifndef FFA_SHARED_MM_BUFFER_OFFSET
> +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_OFFSET 0
> +#endif
> +
> +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_ADDR 0
> +#endif
> +
> +/* MM return codes */
> +#define MM_SUCCESS (0)
> +
> +static const char *mm_sp_svc_uuid = MM_SP_UUID;
> +
> +static u16 mm_sp_id;
> +
> +#endif
> +
>  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
>  static efi_uintn_t max_buffer_size;    /* comm + var + func + data */
>  static efi_uintn_t max_payload_size;   /* func + data */
> @@ -24,6 +59,7 @@ struct mm_connection {
>         u32 session;
>  };
>
> +#if (IS_ENABLED(CONFIG_OPTEE))
>  /**
>   * get_connection() - Retrieve OP-TEE session for a specific UUID.
>   *
> @@ -60,6 +96,7 @@ static int get_connection(struct mm_connection *conn)
>  out:
>         return rc;
>  }
> +#endif
>
>  /**
>   * optee_mm_communicate() - Pass a buffer to StandaloneMM running in OP-TEE
> @@ -70,6 +107,7 @@ out:
>   */
>  static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
>  {
> +#if (IS_ENABLED(CONFIG_OPTEE))
>         ulong buf_size;
>         efi_status_t ret;
>         struct efi_mm_communicate_header *mm_hdr;
> @@ -142,19 +180,269 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
>         }
>
>         return ret;
> +#else
> +       log_err("EFI: Please enable CONFIG_OPTEE for MM comms\n");
> +       return EFI_UNSUPPORTED;
> +#endif
> +}
> +
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))

drop extra brackets

> +
> +/**
> + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> + *
> + * Notify the MM partition in the trusted world that
> + * data is available in the shared buffer.
> + * This is a blocking call during which trusted world has exclusive access
> + * to the MM shared buffer.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_notify_mm_sp(void)
> +{
> +       struct ffa_send_direct_data msg = {0};
> +       int ret;
> +       int sp_event_ret = -1;
> +       struct udevice *dev;
> +
> +       ret = uclass_first_device_err(UCLASS_FFA, &dev);
> +       if (ret) {
> +               log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
> +               return -ENODEV;

return ret

> +       }
> +
> +       msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
> +
> +       ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
> +       if (ret)
> +               return ret;
> +
> +       sp_event_ret = msg.data0; /* x3 */
> +
> +       if (sp_event_ret == MM_SUCCESS)
> +               return 0;
> +
> +       /* Failure to notify the MM SP */
> +
> +       return -EACCES;
> +}
> +
> +/**
> + * ffa_discover_mm_sp_id() - Query the MM partition ID
> + *
> + * Use the FF-A driver to get the MM partition ID.
> + * If multiple partitions are found, use the first one.
> + * This is a boot time function.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_discover_mm_sp_id(void)
> +{
> +       u32 count = 0;
> +       int ret;
> +       struct ffa_partition_info *parts_info;
> +       struct udevice *dev;
> +
> +       ret = uclass_first_device_err(UCLASS_FFA, &dev);
> +       if (ret) {
> +               log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
> +               return -ENODEV;

return ret

Please check that you don't change error returns unless you really
want to, as it makes it hard to debug failures.

> +       }
> +
> +       /* Get from the driver the count of the SPs matching the UUID */
> +       ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, NULL);
> +       if (ret) {
> +               log_err("EFI: Failure in querying SPs count (%d), MM SP discovery failure\n", ret);
> +               return ret;
> +       }
> +
> +       if (!count) {
> +               log_info("EFI: No MM partition found\n");
> +               return ret;
> +       }
> +
> +       /* Pre-allocate a buffer to be filled by the driver with ffa_partition_info structs */
> +
> +       log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
> +
> +       parts_info = calloc(count, sizeof(*parts_info));

Use a local var and drop the calloc()

> +       if (!parts_info)
> +               return -ENOMEM;
> +
> +       /* Ask the driver to fill the buffer with the SPs info */
> +       ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, parts_info);
> +       if (ret) {
> +               log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
> +               free(parts_info);
> +               return ret;
> +       }
> +
> +       /* MM SPs found , use the first one */
> +
> +       mm_sp_id = parts_info[0].id;
> +
> +       log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
> +
> +       free(parts_info);
> +
> +       return 0;
> +}
> +#endif
> +
> +/**
> + * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
> + * @comm_buf:          locally allocated communication buffer used for rx/tx
> + * @dsize:                             communication buffer size
> + *
> + * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
> + * that there is data to read from the shared buffer.
> + * Communication with the MM SP is performed using FF-A transport.
> + * On the event, MM SP can read the data from the buffer and
> + * update the MM shared buffer with response data.
> + * The response data is copied back to the communication buffer.
> + *
> + * Return:
> + *
> + * EFI status code
> + */
> +static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
> +{
> +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))

Please use if() if you can?

> +       ulong tx_data_size;
> +       int ffa_ret;
> +       efi_status_t efi_ret;
> +       struct efi_mm_communicate_header *mm_hdr;
> +       void *virt_shared_buf;
> +
> +       if (!comm_buf)
> +               return EFI_INVALID_PARAMETER;
> +
> +       /* Discover MM partition ID at boot time */
> +       if (!mm_sp_id && ffa_discover_mm_sp_id()) {
> +               log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
> +               return EFI_UNSUPPORTED;
> +       }
> +
> +       mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> +       tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
> +
> +       if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
> +               return EFI_INVALID_PARAMETER;
> +
> +       /* Copy the data to the shared buffer */
> +
> +       virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
> +       memcpy(virt_shared_buf, comm_buf, tx_data_size);
> +
> +       /*
> +        * The secure world might have cache disabled for
> +        * the device region used for shared buffer (which is the case for Optee).
> +        * In this case, the secure world reads the data from DRAM.
> +        * Let's flush the cache so the DRAM is updated with the latest data.
> +        */
> +#ifdef CONFIG_ARM64
> +       invalidate_dcache_all();
> +#endif
> +
> +       /* Announce there is data in the shared buffer */
> +
> +       ffa_ret = ffa_notify_mm_sp();
> +
> +       switch (ffa_ret) {
> +       case 0: {
> +               ulong rx_data_size;
> +               /* Copy the MM SP response from the shared buffer to the communication buffer */
> +               rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> +                       sizeof(efi_guid_t) +
> +                       sizeof(size_t);
> +
> +               if (rx_data_size > comm_buf_size) {
> +                       efi_ret = EFI_OUT_OF_RESOURCES;
> +                       break;
> +               }
> +
> +               memcpy(comm_buf, virt_shared_buf, rx_data_size);
> +               efi_ret = EFI_SUCCESS;
> +               break;
> +       }
> +       case -EINVAL:
> +               efi_ret = EFI_DEVICE_ERROR;
> +               break;
> +       case -EPERM:
> +               efi_ret = EFI_INVALID_PARAMETER;
> +               break;
> +       case -EACCES:
> +               efi_ret = EFI_ACCESS_DENIED;
> +               break;
> +       case -EBUSY:
> +               efi_ret = EFI_OUT_OF_RESOURCES;
> +               break;
> +       default:
> +               efi_ret = EFI_ACCESS_DENIED;
> +       }
> +
> +       unmap_sysmem(virt_shared_buf);
> +       return efi_ret;
> +#else
> +       log_err("EFI: Please enable CONFIG_ARM_FFA_TRANSPORT for MM comms\n");
> +       return EFI_UNSUPPORTED;
> +#endif
> +}
> +
> +/**
> + * select_mm_comms() - detect the available MM transport
> + *
> + * If FF-A is compiled in, make sure the FF-A bus is probed successfully
> + * which means FF-A communication with secure world works and ready
> + * to be used.
> + *
> + * If FF-A is not detected, check if OPTEE support is compiled in.
> + *
> + * Return:
> + *
> + * On success MM_COMMS_FFA or MM_COMMS_OPTEE. Otherwise, MM_COMMS_UNDEFINED
> + */
> +static enum mm_comms_select select_mm_comms(void)
> +{
> +       struct udevice *dev;
> +       int ret;
> +
> +       if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) {
> +               ret = uclass_first_device_err(UCLASS_FFA, &dev);
> +               if (ret)
> +                       log_err("EFI: Cannot find FF-A bus device, cannot select FF-A comms\n");
> +               else
> +                       return MM_COMMS_FFA;
> +       }
> +
> +       if (IS_ENABLED(CONFIG_OPTEE))
> +               return MM_COMMS_OPTEE;
> +
> +       return MM_COMMS_UNDEFINED;
>  }
>
>  /**
> - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
> + * mm_communicate() - Adjust the communication buffer to the MM SP and send
>   * it to OP-TEE
>   *
> - * @comm_buf:          locally allocted communcation buffer
> + * @comm_buf:          locally allocated communication buffer
>   * @dsize:             buffer size
> + *
> + * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
> + * The comm_buf format is the same for both partitions.
> + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> + * When using the u-boot FF-A  driver, any MM SP is supported.
> + *
>   * Return:             status code
>   */
>  static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  {
>         efi_status_t ret;
> +       enum mm_comms_select mm_comms;
>         struct efi_mm_communicate_header *mm_hdr;
>         struct smm_variable_communicate_header *var_hdr;
>
> @@ -162,7 +450,16 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>         mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
>         var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
>
> -       ret = optee_mm_communicate(comm_buf, dsize);
> +       mm_comms = select_mm_comms();
> +       if (mm_comms == MM_COMMS_UNDEFINED) {
> +               ret = EFI_UNSUPPORTED;
> +       } else {
> +               if (mm_comms == MM_COMMS_OPTEE)
> +                       ret = optee_mm_communicate(comm_buf, dsize);
> +               else
> +                       ret = ffa_mm_communicate(comm_buf, dsize);
> +       }
> +
>         if (ret != EFI_SUCCESS) {
>                 log_err("%s failed!\n", __func__);
>                 return ret;
> @@ -258,6 +555,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
>                 goto out;
>         }
>         *size = var_payload->size;
> +
> +       #if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))

Can this use if () ?

> +               if (*size > FFA_SHARED_MM_BUFFER_SIZE)
> +                       *size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE  -
> +                               MM_VARIABLE_COMMUNICATE_SIZE;
> +       #endif
> +
>         /*
>          * There seems to be a bug in EDK2 miscalculating the boundaries and
>          * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> @@ -697,7 +1001,7 @@ void efi_variables_boot_exit_notify(void)
>                 ret = EFI_NOT_FOUND;
>
>         if (ret != EFI_SUCCESS)
> -               log_err("Unable to notify StMM for ExitBootServices\n");
> +               log_err("Unable to notify the MM partition for ExitBootServices\n");
>         free(comm_buf);
>
>         /*
> --
> 2.25.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 04/10] arm_ffa: introduce Arm FF-A support
  2023-04-12  9:42                                                                                           ` [PATCH v11 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-04-19  1:49                                                                                             ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-04-19  1:49 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, trini, u-boot, xueliang.zhong, Heinrich Schuchardt

Hi Abdellatif,

On Wed, 12 Apr 2023 at 03:43, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0
>
> The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World leveraging TrustZone
> technology.
>
> This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> querying the FF-A framework from the secure world.
>
> The driver uses SMC32 calling convention which means using the first
> 32-bit data of the Xn registers.
>
> All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
> which has 64-bit version supported.
>
> Both 32-bit and 64-bit direct messaging are supported which allows both
> 32-bit and 64-bit clients to use the FF-A bus.
>
> FF-A is a discoverable bus and similar to architecture features.
> FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> by the PSCI driver.
>
> Clients are able to probe then use the FF-A bus by calling the DM class
> searching APIs (e.g: uclass_first_device).
>
> The Secure World is considered as one entity to communicate with
> using the FF-A bus. FF-A communication is handled by one device and
> one instance (the bus). This FF-A driver takes care of all the
> interactions between Normal world and Secure World.
>
> The driver exports its operations to be used by upper layers.
>
> Exported operations:
>
> - ffa_partition_info_get
> - ffa_sync_send_receive
> - ffa_rxtx_unmap
>
> 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 please refer to the driver documentation [2].
>
> [1]: https://developer.arm.com/documentation/den0077/latest/
> [2]: doc/arch/arm64.ffa.rst
>
> 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>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
>
> ---
> Changelog:
> ===============
>
> v11:
>
> * move ffa_try_discovery() from the uclass to the Arm FF-A driver
> * rename ffa_try_discovery() to arm_ffa_discover()
> * pass dev as an argument of arm_ffa_discover()
> * add arm_ prefix to the Arm FF-A driver functions
> * add emul field in struct ffa_discovery_info
> * address nits
>
> v10:
>
> * provide the driver operations through the Uclass
> * move the generic FF-A methods to the Uclass
> * keep Arm specific methods in the Arm driver (arm-ffa.c)
> * rename core.c to arm-ffa.c
> * address nits
>
> v9:
>
> * integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
>
> v8:
>
> * make ffa_get_partitions_info() second argument to be an SP count in both
>   modes
> * update ffa_bus_prvdata_get() to return a pointer rather than a pointer
>   address
> * remove packing from ffa_partition_info and ffa_send_direct_data structures
> * pass the FF-A bus device to the bus operations
>
> v7:
>
> * add support for 32-bit direct messaging
> * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> * improve the declaration of error handling mapping
> * stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported
>
> v6:
>
> * drop use of EFI runtime support (We decided with Linaro to add this later)
> * drop discovery from initcalls (discovery will be on demand by FF-A users)
> * set the alignment of the RX/TX buffers to the larger translation granule size
> * move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
> * update the documentation and move it to doc/arch/arm64.ffa.rst
>
> v4:
>
> * add doc/README.ffa.drv
> * moving the FF-A driver work to drivers/firmware/arm-ffa
> * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
>   #if defined by #if CONFIG_IS_ENABLED
> * improving error handling by mapping the FF-A errors to standard errors
>   and logs
> * replacing panics with an error log and returning an error code
> * improving features discovery in FFA_FEATURES by introducing
>   rxtx_min_pages private data field
> * add ffa_remove and ffa_unbind functions
> * improve how the driver behaves when bus discovery is done more than
>   once
>
> v3:
>
> * align the interfaces of the U-Boot FF-A driver with those in the linux
>   FF-A driver
> * remove the FF-A helper layer
> * make the U-Boot FF-A driver independent from EFI
> * provide an optional config that enables copying the driver data to EFI
>   runtime section at ExitBootServices service
> * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
>
> v2:
>
> * make FF-A bus discoverable using device_{bind, probe} APIs
> * remove device tree support
>
> v1:
>
> * introduce FF-A bus driver with device tree support
>
>  MAINTAINERS                                   |    8 +
>  doc/arch/arm64.ffa.rst                        |  271 ++++
>  doc/arch/index.rst                            |    1 +
>  drivers/Makefile                              |    1 +
>  drivers/firmware/Kconfig                      |    1 +
>  drivers/firmware/arm-ffa/Kconfig              |   36 +
>  drivers/firmware/arm-ffa/Makefile             |    8 +
>  drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1143 +++++++++++++++++
>  drivers/firmware/arm-ffa/arm-ffa.c            |  127 ++
>  .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |   14 +
>  include/arm_ffa.h                             |  217 ++++
>  include/arm_ffa_priv.h                        |  271 ++++
>  include/dm/uclass-id.h                        |    6 +
>  13 files changed, 2104 insertions(+)
>  create mode 100644 doc/arch/arm64.ffa.rst
>  create mode 100644 drivers/firmware/arm-ffa/Kconfig
>  create mode 100644 drivers/firmware/arm-ffa/Makefile
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
>  create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
>  create mode 100644 include/arm_ffa.h
>  create mode 100644 include/arm_ffa_priv.h
>

Reviewed-by: Simon Glass <sjg@chromium.org>
nits below

> diff --git a/MAINTAINERS b/MAINTAINERS
> index 086e4cb3df..76f0f276ce 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -266,6 +266,14 @@ F: drivers/net/cortina_ni.h
>  F:     drivers/net/phy/ca_phy.c
>  F:     configs/cortina_presidio-asic-pnand_defconfig
>
> +ARM FF-A
> +M:     Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +S:     Maintained
> +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>
>  M:     Fabio Estevam <festevam@gmail.com>
> diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> new file mode 100644
> index 0000000000..466e77e3cd
> --- /dev/null
> +++ b/doc/arch/arm64.ffa.rst
> @@ -0,0 +1,271 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +
> +Arm FF-A Support
> +================
> +
> +Summary
> +-------
> +
> +FF-A stands for Firmware Framework for Arm A-profile processors.
> +
> +FF-A specifies interfaces that enable a pair of software sandboxes to

This is confusing as we use 'sandbox' in U-Boot to mean something else.

To me, a sandbox is a play area where you can fiddle around, like kids
in a sandbox.

It is widely used though, to mean a secure environment, which is
unfortunate. I think a 'jail' or 'secure container' container would be
a better name.

Anyway, for here, could you just put in brackets:

(not to be confused with the U-Boot sandbox build)

or something like that.


> +communicate with each other. A sandbox aka partition could
> +be a VM in the Normal or Secure world, an application in S-EL0, or a
> +Trusted OS in S-EL1.
> +
> +The U-Boot FF-A support (the bus) implements the interfaces to communicate
> +with partitions in the Secure world aka Secure partitions (SPs).
> +
> +The FF-A support specifically focuses on communicating with SPs that
> +isolate portions of EFI runtime services that must run in a protected
> +environment which is inaccessible by the Host OS or Hypervisor.
> +Examples of such services are set/get variables.
> +
> +The FF-A support uses the SMC ABIs defined by the FF-A specification to:
> +
> +- Discover the presence of SPs of interest
> +- Access an SP's service through communication protocols
> +  e.g. EFI MM communication protocol
> +
> +At this stage of development only EFI boot time is supported.

How about: 'EFI boot-time services'  are supported

> +Runtime support will be added in future developments.
> +
> +The U-Boot FF-A support provides the following parts:
> +
> +- A Uclass driver providing generic FF-A methods.
> +- An Arm FF-A driver providing Arm specific methods and reusing the Uclass methods.

Arm-specific

> +
> +FF-A and SMC specifications
> +-------------------------------------------
> +
> +The current implementation of the U-Boot FF-A support relies on FF-A
> +specification v1.0

Can you put a nice link here so people can click on it? You can do that in rST.

and uses SMC32 calling convention which means using
> +the first 32-bit data of the Xn registers.
> +
> +At this stage we only need the FF-A v1.0 features.
> +
> +The FF-A support has been tested with OP-TEE which supports SMC32 calling
> +convention.
> +
> +For more details please refer to the FF-A v1.0 spec:
> +https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token=

same here (and drop the ?token=)
> +
> +Hypervisors are supported if they are configured to trap SMC calls.
> +
> +The FF-A support uses 64-bit registers as per SMCCCv1.2 specification.
> +
> +For more details please refer to the SMC Calling Convention v1.2 spec:
> +https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

same here

> +
> +Supported hardware
> +--------------------------------
> +
> +Aarch64 plaforms
> +
> +Configuration
> +----------------------
> +
> +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.
> +
> +FF-A ABIs under the hood
> +---------------------------------------
> +
> +Invoking an FF-A ABI involves providing to the secure world/hypervisor the
> +expected arguments from the ABI.
> +
> +On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers.
> +Then, an SMC instruction is executed.
> +
> +At the secure side level or hypervisor the ABI is handled at a higher exception
> +level and the arguments are read and processed.
> +
> +The response is put back through x0 to x7 registers and control is given back
> +to the U-Boot Arm FF-A driver (non-secure world).
> +
> +The driver reads the response and processes it accordingly.
> +
> +This methodology applies to all the FF-A ABIs.
> +
> +FF-A bus discovery on Arm 64-bit platforms
> +---------------------------------------------
> +
> +When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
> +an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
> +This discovery mechanism is performed by the PSCI driver.
> +
> +The PSCI driver comes with a PSCI device tree node which is the root node for all
> +architecture features including FF-A bus.
> +
> +::
> +
> +   => dm tree
> +
> +    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.
> +
> +In case of FF-A, the callback is arm_ffa_is_supported() which tries to discover the
> +FF-A framework by querying the FF-A framework version from secure world using
> +FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
> +mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver
> +with the device using device_bind_driver().
> +
> +At this stage the FF-A bus is registered with the DM and can be interacted with using
> +the DM APIs.
> +
> +Clients are able to probe then use the FF-A bus by calling uclass_first_device().
> +Please refer to the armffa command implementation as an example of how to probe
> +and interact with the FF-A bus.
> +
> +When calling uclass_first_device(), the FF-A driver is probed and ends up calling
> +ffa_do_probe() provided by the Uclass which does the following:
> +
> +    - updating uc_priv with discovery information
> +    - querying from secure world the u-boot endpoint ID
> +    - querying from secure world the supported features of FFA_RXTX_MAP
> +    - mapping the RX/TX buffers
> +    - querying from secure world all the partitions information
> +
> +When one of the above actions fails, probing fails and the driver stays not active
> +and can be probed again if needed.
> +
> +FF-A device destruction
> +-------------------------
> +
> +When the FF-A device is removed by the DM, RX/TX buffers are automatically
> +unmapped and freed.
> +
> +For example, at EFI efi_exit_boot_services() active devices are automatically removed
> +by dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL).
> +
> +By consequence, the FF-A RX/TX are unmapped automatically.
> +
> +Requirements for clients
> +-------------------------------------
> +
> +When using the FF-A bus with EFI, clients must query the SPs they are looking for
> +during EFI boot time mode using the service UUID.

boot-time

> +
> +The RX/TX buffers are only available at EFI boot time. Querying partitions is
> +done at boot time and data is cached for future use.
> +
> +RX/TX buffers should be unmapped before EFI runtime mode starts.
> +The driver provides a bus operation for that called ffa_rxtx_unmap() and this is done
> +automatically at efi_exit_boot_services().
> +
> +If  RX/TX buffers created by U-Boot are not unmapped and by consequence becoming
> +available at EFI runtime, secure world will get confused about RX/TX buffers
> +ownership (U-Boot vs kernel).

Can you rewrite that a bit? It seems quite strange English.

> +
> +When invoking FF-A direct messaging, clients should specify which ABI protocol
> +they want to use (32-bit vs 64-bit). Selecting the protocol means using
> +the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> +The calling convention between U-Boot and the secure world stays the same: SMC32.
> +
> +The bus driver layer
> +------------------------------
> +
> +FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c
> +
> +The following features are provided:
> +
> +- Support for the 32-bit version of the following ABIs:
> +
> +    - FFA_VERSION
> +    - FFA_ID_GET
> +    - FFA_FEATURES
> +    - FFA_PARTITION_INFO_GET
> +    - FFA_RXTX_UNMAP
> +    - FFA_RX_RELEASE
> +    - FFA_RUN
> +    - FFA_ERROR
> +    - FFA_SUCCESS
> +    - FFA_INTERRUPT
> +    - FFA_MSG_SEND_DIRECT_REQ
> +    - FFA_MSG_SEND_DIRECT_RESP
> +
> +- Support for the 64-bit version of the following ABIs:
> +
> +    - FFA_RXTX_MAP
> +    - FFA_MSG_SEND_DIRECT_REQ
> +    - FFA_MSG_SEND_DIRECT_RESP
> +
> +- Processing the received data from the secure world/hypervisor and caching it
> +
> +- Hiding from upper layers the FF-A protocol and registers details. Upper
> +  layers focus on exchanged data, FF-A support takes care of how to transport
> +  that to the secure world/hypervisor using FF-A
> +
> +- FF-A support provides driver operations to be used by upper layers:
> +
> +    - ffa_partition_info_get
> +    - ffa_sync_send_receive
> +    - ffa_rxtx_unmap
> +
> +- FF-A bus discovery makes sure FF-A framework is responsive and compatible
> +  with the driver
> +
> +- FF-A bus can be compiled and used without EFI
> +
> +Example of boot logs with FF-A enabled
> +--------------------------------------
> +
> +For example, when using FF-A with Corstone-1000 the logs are as follows:
> +
> +::
> +
> +   U-Boot 2023.01 (Mar 27 2023 - 13:48:33 +0000) corstone1000 aarch64
> +
> +   DRAM:  2 GiB
> +   Arm FF-A framework discovery
> +   Using Arm SMC for FF-A conduit
> +   FF-A driver 1.0
> +   FF-A framework 1.0
> +   FF-A versions are compatible
> +   ...
> +   Hit any key to stop autoboot:  0
> +   Loading kernel from 0x083EE000 to memory ...
> +   ...
> +   FF-A endpoint ID is 0
> +   Using 1 4KB page(s) for FF-A RX/TX buffers size
> +   FF-A RX buffer at virtual address 00000000fdf4f000
> +   FF-A TX buffer at virtual address 00000000fdf51000
> +   FF-A RX/TX buffers mapped
> +   Reading FF-A partitions data from the RX buffer
> +   FF-A partition ID 8001 : info cached
> +   FF-A partition ID 8002 : info cached
> +   FF-A partition ID 8003 : info cached
> +   3 FF-A partition(s) found and cached
> +   Preparing for checking FF-A partitions count
> +   Searching FF-A partitions using the provided UUID
> +   No FF-A partition found. Querying framework ...
> +   Reading FF-A partitions data from the RX buffer
> +   Number of FF-A partition(s) matching the UUID: 1
> +   EFI: Pre-allocating 1 partition(s) info structures
> +   Preparing for filling FF-A partitions info
> +   Searching FF-A partitions using the provided UUID
> +   FF-A partition ID 8003 matches the provided UUID
> +   EFI: MM partition ID 0x8003
> +   EFI: Corstone1000: Capsule shared buffer at 0x80000000 , size 8192 pages
> +   Booting /MemoryMapped(0x0,0x88200000,0xf00000)
> +   EFI stub: Booting Linux Kernel...
> +   EFI stub: Using DTB from configuration table
> +   EFI stub: Exiting boot services...
> +   unmapping FF-A RX/TX buffers
> +   Freeing FF-A RX/TX buffers
> +   Booting Linux on physical CPU 0x0000000000 [0x411fd040]
> +   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
> +   Machine model: ARM Corstone1000 FPGA MPS3 board
> +
> +Contributors
> +------------
> +   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> diff --git a/doc/arch/index.rst b/doc/arch/index.rst
> index b8da4b8c8e..2f916f4026 100644
> --- a/doc/arch/index.rst
> +++ b/doc/arch/index.rst
> @@ -8,6 +8,7 @@ Architecture-specific doc
>
>     arc
>     arm64
> +   arm64.ffa
>     m68k
>     mips
>     nios2
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 58be410135..885fdef4dc 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -112,6 +112,7 @@ obj-y += iommu/
>  obj-y += smem/
>  obj-y += thermal/
>  obj-$(CONFIG_TEE) += tee/
> +obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
>  obj-y += axi/
>  obj-y += ufs/
>  obj-$(CONFIG_W1) += w1/
> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
> index eae1c8ddc9..8789b1ea14 100644
> --- a/drivers/firmware/Kconfig
> +++ b/drivers/firmware/Kconfig
> @@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
>           the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
>           services if any and reported as supported by the SMCCC firmware.
>
> +source "drivers/firmware/arm-ffa/Kconfig"
>  source "drivers/firmware/scmi/Kconfig"
> diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> new file mode 100644
> index 0000000000..9200c8028b
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/Kconfig
> @@ -0,0 +1,36 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +config ARM_FFA_TRANSPORT
> +       bool "Enable Arm Firmware Framework for Armv8-A driver"
> +       depends on DM && ARM64
> +       select ARM_SMCCC
> +       select ARM_SMCCC_FEATURES
> +       select LIB_UUID
> +       select DEVRES
> +       help
> +         The Firmware Framework for Arm A-profile processors (FF-A)
> +         describes interfaces (ABIs) that standardize communication
> +         between the Secure World and Normal World leveraging TrustZone
> +         technology.
> +
> +         The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32
> +         calling convention.
> +
> +         FF-A specification:
> +
> +         https://developer.arm.com/documentation/den0077/a/?lang=en
> +
> +         In U-Boot FF-A design, FF-A is considered as a discoverable bus.
> +         FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> +         by the PSCI driver.
> +         The Secure World is considered as one entity to communicate with
> +         using the FF-A bus.
> +         FF-A communication is handled by one device and one instance (the bus).
> +         The FF-A support on U-Boot  takes care of all the interactions between Normal
> +         world and Secure World.
> +
> +         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
> +
> diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
> new file mode 100644
> index 0000000000..11b1766285
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/Makefile
> @@ -0,0 +1,8 @@
> +# 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>
> +
> +obj-y += arm-ffa-uclass.o arm-ffa.o
> diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> new file mode 100644
> index 0000000000..c3ad19b8e7
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> @@ -0,0 +1,1143 @@
> +// 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 <arm_ffa_priv.h>
> +#include <dm.h>
> +#include <log.h>
> +#include <malloc.h>
> +#include <string.h>
> +#include <uuid.h>
> +#include <asm/global_data.h>
> +#include <dm/device-internal.h>
> +#include <dm/devres.h>
> +#include <dm/root.h>
> +#include <linux/errno.h>
> +#include <linux/sizes.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;

> +
> +/* FF-A discovery information */
> +struct ffa_discovery_info dscvry_info;

This should be in the uclass priv data, right? We try to avoid global
vars in driver model.
[..]

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 05/10] arm_ffa: introduce armffa command
  2023-04-12  9:42                                                                                           ` [PATCH v11 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
  2023-04-12 14:02                                                                                             ` Heinrich Schuchardt
@ 2023-04-19  1:49                                                                                             ` Simon Glass
  2023-05-12 12:14                                                                                               ` Abdellatif El Khlifi
  1 sibling, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-04-19  1:49 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, trini, u-boot, xueliang.zhong, Heinrich Schuchardt

Hi Abdellatif,

On Wed, 12 Apr 2023 at 03:43, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Provide armffa command showcasing the use of the U-Boot FF-A support
>
> armffa is a command showcasing how to invoke FF-A operations.
> This provides a guidance to the client developers on how to
> call the FF-A bus interfaces. The command also allows to gather secure
> partitions information and ping these  partitions. The command is also
> helpful in testing the communication with secure partitions.
>
> For more details please refer to the command documentation [1].
>
> [1]: doc/usage/cmd/armffa.rst
>
> 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>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
>
> ---
> Changelog:
> ===============
>
> v11:
>
> * use U_BOOT_CMD_WITH_SUBCMDS
> * address nits
>
> v10:
>
> * use the FF-A driver Uclass operations
> * use uclass_first_device()
> * address nits
>
> v9:
>
> * remove manual FF-A discovery and use DM
> * use DM class APIs to probe and interact with the FF-A bus
> * add doc/usage/cmd/armffa.rst
>
> v8:
>
> * update partition_info_get() second argument to be an SP count
> * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7:
>
> * adapt do_ffa_dev_list() following the recent update on
>   uclass_first_device/uclass_next_device functions (they return void now)
> * set armffa command to use 64-bit direct messaging
>
> v4:
>
> * remove pattern data in do_ffa_msg_send_direct_req
>
> v3:
>
> * use the new driver interfaces (partition_info_get, sync_send_receive)
>   in armffa command
>
> v2:
>
> * replace use of ffa_helper_init_device function by
>  ffa_helper_bus_discover
>
> v1:
>
> * introduce armffa command
>
>  MAINTAINERS                      |   2 +
>  cmd/Kconfig                      |  10 ++
>  cmd/Makefile                     |   2 +
>  cmd/armffa.c                     | 212 +++++++++++++++++++++++++++++++
>  doc/arch/arm64.ffa.rst           |   7 +
>  doc/usage/cmd/armffa.rst         | 105 +++++++++++++++
>  doc/usage/index.rst              |   1 +
>  drivers/firmware/arm-ffa/Kconfig |   1 +
>  8 files changed, 340 insertions(+)
>  create mode 100644 cmd/armffa.c
>  create mode 100644 doc/usage/cmd/armffa.rst
>

Reviewed-by: Simon Glass <sjg@chromium.org>

with nits below

For your docs, please use a proper rST link for
doc/usage/cmd/armffa.rst so people can click on it and view the
command docs.

Also:

armffa is an implementation-defined command

(add hyphen)

although I'm not sure how an implementation can define the command?

The example output in your 'example' docs is very, very verbose.
Shouldn't it just report problems?

> diff --git a/MAINTAINERS b/MAINTAINERS
> index 76f0f276ce..c64804ca2d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -269,7 +269,9 @@ F:  configs/cortina_presidio-asic-pnand_defconfig
>  ARM FF-A
>  M:     Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>  S:     Maintained
> +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
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 8c9b430f99..4cb0b2c167 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -934,6 +934,16 @@ endmenu
>
>  menu "Device access commands"
>
> +config CMD_ARMFFA
> +       bool "Arm FF-A test command"
> +       depends on ARM_FFA_TRANSPORT
> +       help
> +         Provides a test command for the FF-A support
> +         supported options:
> +               - Listing the partition(s) info
> +               - Sending a data pattern to the specified partition
> +               - Displaying the arm_ffa device info
> +
>  config CMD_ARMFLASH
>         #depends on FLASH_CFI_DRIVER
>         bool "armflash"
> diff --git a/cmd/Makefile b/cmd/Makefile
> index e032091621..9130b9078d 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -12,6 +12,8 @@ obj-y += panic.o
>  obj-y += version.o
>
>  # command
> +

Please drop blank line

> +obj-$(CONFIG_CMD_ARMFFA) += armffa.o
>  obj-$(CONFIG_CMD_ACPI) += acpi.o
>  obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
>  obj-$(CONFIG_CMD_AES) += aes.o
> diff --git a/cmd/armffa.c b/cmd/armffa.c
> new file mode 100644
> index 0000000000..ab88412c7d
> --- /dev/null
> +++ b/cmd/armffa.c
> @@ -0,0 +1,212 @@
> +// 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 <command.h>
> +#include <dm.h>
> +#include <mapmem.h>
> +#include <stdlib.h>
> +#include <asm/io.h>
> +
> +/**
> + * ffa_get_dev() - Return the FF-A device
> + * @devp:      pointer to the FF-A device
> + *
> + * Search for the FF-A device.
> + *
> + * Return:
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_get_dev(struct udevice **devp)
> +{
> +       int ret;
> +
> +       ret = uclass_first_device_err(UCLASS_FFA, devp);
> +       if (ret) {
> +               log_err("Cannot find FF-A bus device\n");
> +               return -ENODEV;

return ret

> +       }
> +
> +       return 0;
> +}
> +
> +/**
> + * do_ffa_getpart() - implementation of the getpart subcommand
> + * @cmdtp:             Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * Query the secure partition information which the UUID is provided
> + * as an argument. The function uses the arm_ffa driver
> + * partition_info_get operation which implements FFA_PARTITION_INFO_GET
> + * ABI to retrieve the data. The input UUID string is expected to be in big
> + * endian format.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
> +                         char *const argv[])
> +{
> +       u32 count = 0;
> +       int ret;
> +       struct ffa_partition_info *parts_info;
> +       u32 i;
> +       struct udevice *dev;
> +
> +       ret = ffa_get_dev(&dev);
> +       if (ret)
> +               return CMD_RET_FAILURE;
> +
> +       /* Mode 1: getting the number of secure partitions */
> +       ret = ffa_partition_info_get(dev, argv[1], &count, NULL);
> +       if (ret) {
> +               log_err("Failure in querying partitions count (error code: %d)\n", ret);
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       if (!count) {
> +               log_info("No secure partition found\n");
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       /*
> +        * Pre-allocate a buffer to be filled by the driver
> +        * with ffa_partition_info structs
> +        */
> +
> +       log_info("Pre-allocating %d partition(s) info structures\n", count);
> +
> +       parts_info = calloc(count, sizeof(struct ffa_partition_info));

This should be a local variable:

struct ffa_partition_info parts_info

I mentioned this before and you said that the number of things is
fixed at runtime, but I don't see that here. Also I see is a simple
struct, so there should be no need to allocate it.

> +       if (!parts_info)
> +               return CMD_RET_FAILURE;
> +
> +       /* Ask the driver to fill the buffer with the SPs info */
> +
> +       ret = ffa_partition_info_get(dev, argv[1], &count, parts_info);
> +       if (ret) {
> +               log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
> +               free(parts_info);
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       /* SPs found , show the partition information */
> +       for (i = 0; i < count ; i++) {
> +               log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
> +                        parts_info[i].id,
> +                        parts_info[i].exec_ctxt,
> +                        parts_info[i].properties);
> +       }
> +
> +       free(parts_info);
> +
> +       return CMD_RET_SUCCESS;
> +}
> +
[..]

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 06/10] arm_ffa: introduce sandbox FF-A support
  2023-04-12  9:42                                                                                           ` [PATCH v11 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
@ 2023-04-19  1:49                                                                                             ` Simon Glass
  2023-05-03 17:56                                                                                               ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-04-19  1:49 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, trini, u-boot, xueliang.zhong, Heinrich Schuchardt

Hi Abdellatif,

On Wed, 12 Apr 2023 at 03:43, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> 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>
> 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>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
>
> ---
> Changelog:
> ===============
>
> v11:
>
> * rename ffa_try_discovery() to sandbox_ffa_discover()
> * rename sandbox_ffa_query_core_state() to sandbox_query_ffa_emul_state()
> * store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
> * set the emulator as parent of the sandbox FF-A device

This is close, but not quite what I expected.

I suspect the emulator should be the child of the FF-A device, not the
parent? You should update the devicetree to show that. You should not
need to reparent anything.

Then you put this in your FFA uclass so it binds the emulator:

.post_bind = dm_scan_fdt_dev,

Finding the emulator is probably then just a case of calling
device_find_first_child().

I notice that you are sometimes breaking lines very short, e.g. the
memset() lines. Please try to use all 80cols if you can.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA
  2023-04-12  9:42                                                                                           ` [PATCH v11 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-04-19  1:50                                                                                             ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-04-19  1:50 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, trini, u-boot, xueliang.zhong, Heinrich Schuchardt

On Wed, 12 Apr 2023 at 03:43, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add functional test cases for the FF-A support
>
> These tests rely on the FF-A sandbox emulator and FF-A
> sandbox driver which help in inspecting the FF-A communication.
>
> 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>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
>
> ---
> Changelog:
> ===============
>
> v11:
>
> * drop unmapping test (taken care of by the DM when removing the device)
> * address nits
>
> v10:
>
> * use the FF-A driver Uclass operations
> * use uclass_first_device()
> * replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT
> * address nits
>
> v9: align FF-A sandbox tests with FF-A discovery through DM
>
> v8:
>
>   * update partition_info_get() second argument to be an SP count
>   * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7: set the tests to use 64-bit direct messaging
>
> v4: align sandbox tests with the new FF-A driver interfaces
>  and new way of error handling
>
> v1: introduce sandbox tests
>
>  MAINTAINERS            |   1 +
>  doc/arch/arm64.ffa.rst |   1 +
>  test/dm/Makefile       |   2 +
>  test/dm/ffa.c          | 258 +++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 262 insertions(+)
>  create mode 100644 test/dm/ffa.c

Reviewed-by: Simon Glass <sjg@chromium.org>

nits below

>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d7caad3bd4..cd99e655db 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -276,6 +276,7 @@ F:  doc/arch/arm64.ffa.rst
>  F:     doc/usage/cmd/armffa.rst
>  F:     drivers/firmware/arm-ffa/
>  F:     include/arm_ffa.h
> +F:     test/dm/ffa.c
>
>  ARM FREESCALE IMX
>  M:     Stefano Babic <sbabic@denx.de>
> diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> index 431c29f921..fdcb008d72 100644
> --- a/doc/arch/arm64.ffa.rst
> +++ b/doc/arch/arm64.ffa.rst
> @@ -38,6 +38,7 @@ The U-Boot FF-A support provides the following parts:
>    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.
> +- Sandbox FF-A test cases.
>
>  FF-A and SMC specifications
>  -------------------------------------------
> diff --git a/test/dm/Makefile b/test/dm/Makefile
> index 7a79b6e1a2..45563bdfb4 100644
> --- a/test/dm/Makefile
> +++ b/test/dm/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0+
>  #
>  # Copyright (c) 2013 Google, Inc
> +# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
>
>  obj-$(CONFIG_UT_DM) += test-dm.o
>
> @@ -85,6 +86,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
>  obj-$(CONFIG_ACPI_PMC) += pmc.o
>  obj-$(CONFIG_DM_PMIC) += pmic.o
>  obj-$(CONFIG_DM_PWM) += pwm.o
> +obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o
>  obj-$(CONFIG_QFW) += qfw.o
>  obj-$(CONFIG_RAM) += ram.o
>  obj-y += regmap.o
> diff --git a/test/dm/ffa.c b/test/dm/ffa.c
> new file mode 100644
> index 0000000000..ace2582e22
> --- /dev/null
> +++ b/test/dm/ffa.c
> @@ -0,0 +1,258 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Functional tests for UCLASS_FFA  class
> + *
> + * 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 <console.h>
> +#include <dm.h>
> +#include <asm/sandbox_arm_ffa.h>
> +#include <asm/sandbox_arm_ffa_priv.h>
> +#include <dm/test.h>
> +#include <test/test.h>
> +#include <test/ut.h>
> +
> +/* Functional tests for the UCLASS_FFA */
> +
> +static int check_fwk_version(struct ffa_priv *uc_priv, struct unit_test_state *uts)
> +{
> +       struct ffa_sandbox_data func_data;
> +       u32 fwk_version = 0;
> +
> +       func_data.data0 = &fwk_version;
> +       func_data.data0_size = sizeof(fwk_version);
> +       ut_assertok(sandbox_query_ffa_emul_state(FFA_VERSION, &func_data));
> +       ut_asserteq(uc_priv->dscvry_info.fwk_version, fwk_version);
> +
> +       return 0;
> +}
> +
> +static int check_endpoint_id(struct ffa_priv *uc_priv, struct unit_test_state *uts)
> +{
> +       ut_asserteq(0, uc_priv->id);
> +
> +       return 0;
> +}
> +
> +static int check_rxtxbuf(struct ffa_priv *uc_priv, struct unit_test_state *uts)
> +{
> +       ut_assertnonnull(uc_priv->pair.rxbuf);
> +       ut_assertnonnull(uc_priv->pair.txbuf);
> +
> +       return 0;
> +}
> +
> +static int check_features(struct ffa_priv *uc_priv, struct unit_test_state *uts)
> +{
> +       ut_assert(uc_priv->pair.rxtx_min_pages == RXTX_4K ||
> +                 uc_priv->pair.rxtx_min_pages == RXTX_16K ||
> +                 uc_priv->pair.rxtx_min_pages == RXTX_64K);
> +
> +       return 0;
> +}
> +
> +static int check_rxbuf_mapped_flag(u32 queried_func_id,
> +                                  u8 rxbuf_mapped,
> +                                  struct unit_test_state *uts)
> +{
> +       switch (queried_func_id) {
> +       case FFA_RXTX_MAP:
> +               ut_asserteq(1, rxbuf_mapped);
> +               break;
> +       case FFA_RXTX_UNMAP:
> +               ut_asserteq(0, rxbuf_mapped);
> +               break;
> +       default:
> +               ut_assert(false);
> +       }
> +
> +       return 0;
> +}
> +
> +static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
> +{
> +       ut_asserteq(0, rxbuf_owned);
> +
> +       return 0;
> +}
> +
> +static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
> +{
> +       struct ffa_send_direct_data msg;
> +       u8 cnt;
> +       struct udevice *dev;
> +
> +       ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
> +
> +       ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
> +
> +       for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
> +               ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]);
> +
> +       return 0;
> +}
> +
> +static int test_partitions_and_comms(const char *service_uuid,
> +                                    struct unit_test_state *uts)
> +{
> +       struct ffa_partition_info parts_info[SANDBOX_SP_COUNT_PER_VALID_SERVICE] = {0};
> +       u32 count, info_idx, exp_info_idx, valid_sps = 0;
> +       struct udevice *dev;
> +       struct ffa_sandbox_data func_data;
> +       struct ffa_partitions *partitions;
> +
> +       ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
> +
> +       /* Get from the driver the count of the SPs matching the UUID */
> +       ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, NULL));
> +       /* Make sure partitions are detected */
> +       ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
> +
> +       /* Ask the driver to fill the buffer with the SPs info */
> +       ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, parts_info));
> +
> +       /* SPs found , verify the partitions information */
> +
> +       func_data.data0 = &partitions;
> +       func_data.data0_size = sizeof(struct ffa_partitions *);
> +       ut_assertok(sandbox_query_ffa_emul_state(FFA_PARTITION_INFO_GET, &func_data));
> +
> +       for (info_idx = 0; info_idx < count ; info_idx++) {

Use i as the index var ?

> +               for (exp_info_idx = 0;
> +                    exp_info_idx < partitions->count;
> +                    exp_info_idx++) {
> +                       if (parts_info[info_idx].id ==
> +                          partitions->descs[exp_info_idx].info.id) {
> +                               valid_sps++;
> +                               ut_asserteq_mem(&parts_info[info_idx],
> +                                               &partitions->descs[exp_info_idx]
> +                                               .info,
> +                                               sizeof(struct ffa_partition_info));
> +                               /* Send and receive data from the current partition */
> +                               test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts);
> +                       }
> +               }
> +       }
> +
> +       /* Verify expected partitions found in the emulated secure world */
> +       ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, valid_sps);
> +
> +       return 0;
> +}
> +
> +static int dm_test_ffa_ack(struct unit_test_state *uts)
> +{
> +       struct ffa_priv *uc_priv;
> +       struct ffa_sandbox_data func_data;
> +       u8 rxbuf_flag = 0;
> +       const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
> +       const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
> +       struct udevice *dev;
> +
> +       /* Test probing the sandbox FF-A bus */
> +       ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
> +
> +       /* Get a pointer to the sandbox FF-A bus private data */
> +       uc_priv = dev_get_uclass_priv(dev);
> +
> +       /* Make sure the private data pointer is retrieved */
> +       ut_assertnonnull(uc_priv);
> +
> +       /* Test FFA_VERSION */
> +       check_fwk_version(uc_priv, uts);
> +
> +       /* Test FFA_ID_GET */
> +       check_endpoint_id(uc_priv, uts);
> +
> +       /* Test FFA_FEATURES */
> +       check_features(uc_priv, uts);
> +
> +       /*  Test RX/TX buffers */
> +       check_rxtxbuf(uc_priv, uts);
> +
> +       /* Test FFA_RXTX_MAP */
> +       func_data.data0 = &rxbuf_flag;
> +       func_data.data0_size = sizeof(rxbuf_flag);
> +
> +       rxbuf_flag = 0;
> +       sandbox_query_ffa_emul_state(FFA_RXTX_MAP, &func_data);
> +       check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts);
> +
> +       /* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
> +       test_partitions_and_comms(svc1_uuid, uts);
> +
> +       /* Test FFA_RX_RELEASE */
> +       rxbuf_flag = 1;
> +       sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data);
> +       check_rxbuf_release_flag(rxbuf_flag, uts);
> +
> +       /* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
> +       test_partitions_and_comms(svc2_uuid, uts);
> +
> +       /* Test FFA_RX_RELEASE */
> +       rxbuf_flag = 1;
> +       ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data));
> +       check_rxbuf_release_flag(rxbuf_flag, uts);
> +
> +       return 0;
> +}
> +
> +DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
> +
> +static int dm_test_ffa_nack(struct unit_test_state *uts)
> +{
> +       struct ffa_priv *uc_priv;
> +       const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
> +       const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
> +       const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
> +       struct ffa_send_direct_data msg;
> +       int ret;
> +       u32 count;
> +       u16 part_id = 0;
> +       struct udevice *dev;
> +
> +       /* Test probing the sandbox FF-A bus */
> +       ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
> +
> +       /* Get a pointer to the sandbox FF-A bus private data */
> +       uc_priv = dev_get_uclass_priv(dev);
> +
> +       /* Make sure the private data pointer is retrieved */
> +       ut_assertnonnull(uc_priv);
> +
> +       /* Query partitions count using  invalid arguments */
> +       ret = ffa_partition_info_get(dev, unvalid_svc_uuid, NULL, NULL);
> +       ut_asserteq(-EINVAL, ret);
> +
> +       /* Query partitions count using an invalid UUID  string */
> +       ret = ffa_partition_info_get(dev, unvalid_svc_uuid_str, &count, NULL);
> +       ut_asserteq(-EINVAL, ret);
> +
> +       /* Query partitions count using an invalid UUID (no matching SP) */
> +       count = 0;
> +       ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, NULL);
> +       ut_assertok(count);

ut_assertok() is supposed to be used for error returns. So this should be:

ut_asserteq(0, count)

> +
> +       /* Query partitions count using a valid UUID */
> +       count = 0;
> +       ut_assertok(ffa_partition_info_get(dev, valid_svc_uuid, &count, NULL));
> +       /* Make sure partitions are detected */
> +       ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
> +
> +       /* Send data to an invalid partition */
> +       ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
> +       ut_asserteq(-EINVAL, ret);
> +
> +       /* Send data to a valid partition */
> +       part_id = uc_priv->partitions.descs[0].info.id;
> +       ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
> +
> +       return 0;
> +}
> +
> +DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
> --
> 2.25.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 08/10] arm_ffa: introduce armffa command Sandbox test
  2023-04-12  9:42                                                                                           ` [PATCH v11 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2023-04-19  1:50                                                                                             ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-04-19  1:50 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, trini, u-boot, xueliang.zhong

Hi Abdellatif,

On Wed, 12 Apr 2023 at 03:43, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add Sandbox test for the armffa command
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 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>
>
> ---
> Changelog:
> ===============
>
> v10:
>
> * replace CMD_RET_SUCCESS with 0
> * replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT
>
> v9: align the test with FF-A discovery through DM
>
> v4: drop use of helper APIs
>
> v1: introduce armffa command sandbox test
>
>  MAINTAINERS       |  1 +
>  test/cmd/Makefile |  2 ++
>  test/cmd/armffa.c | 39 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 42 insertions(+)
>  create mode 100644 test/cmd/armffa.c

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index cd99e655db..67eed92a9b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -276,6 +276,7 @@ F:  doc/arch/arm64.ffa.rst
>  F:     doc/usage/cmd/armffa.rst
>  F:     drivers/firmware/arm-ffa/
>  F:     include/arm_ffa.h
> +F:     test/cmd/armffa.c
>  F:     test/dm/ffa.c
>
>  ARM FREESCALE IMX
> diff --git a/test/cmd/Makefile b/test/cmd/Makefile
> index 055adc65a2..1d1dbb4fbc 100644
> --- a/test/cmd/Makefile
> +++ b/test/cmd/Makefile
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0+
>  #
>  # Copyright (c) 2013 Google, Inc
> +# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
>
>  ifdef CONFIG_HUSH_PARSER
>  obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
> @@ -23,6 +24,7 @@ obj-$(CONFIG_CMD_SEAMA) += seama.o
>  ifdef CONFIG_SANDBOX
>  obj-$(CONFIG_CMD_READ) += rw.o
>  obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
> +obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o
>  endif
>  obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
>  obj-$(CONFIG_CMD_WGET) += wget.o
> diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
> new file mode 100644
> index 0000000000..a9768dbd2c
> --- /dev/null
> +++ b/test/cmd/armffa.c
> @@ -0,0 +1,39 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Test for armffa command
> + *
> + * 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 <string.h>
> +#include <asm/sandbox_arm_ffa.h>
> +#include <dm/test.h>
> +#include <test/test.h>
> +#include <test/ut.h>
> +
> +#define PING_CMD_SIZE 19
> +
> +/* Basic test of 'armffa' command */
> +static int dm_test_armffa_cmd(struct unit_test_state *uts)
> +{
> +       char ping_cmd[PING_CMD_SIZE] = {0};

No need to assign a value for something that gets written in the function.

> +
> +       /* armffa getpart <UUID> */
> +       ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
> +
> +       snprintf(ping_cmd, PING_CMD_SIZE, "armffa ping 0x%x", SANDBOX_SP1_ID);
> +
> +       /* armffa ping <ID> */
> +       ut_assertok(run_command(ping_cmd, 0));

See run_commandf() so you can =avoid the sprintf()

> +
> +       /* armffa devlist */
> +       ut_assertok(run_command("armffa devlist", 0));
> +
> +       return 0;
> +}
> +
> +DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
> --
> 2.25.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-04-12  9:42                                                                                           ` [PATCH v11 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
  2023-04-19  1:49                                                                                             ` Simon Glass
@ 2023-04-21  8:10                                                                                             ` Ilias Apalodimas
  1 sibling, 0 replies; 478+ messages in thread
From: Ilias Apalodimas @ 2023-04-21  8:10 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, jens.wiklander, nd, robh, sjg, trini,
	u-boot, xueliang.zhong, Gowtham Suresh Kumar

Hi Abdellatif,

[...]

>
> @@ -162,7 +450,16 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
>  	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
>
> -	ret = optee_mm_communicate(comm_buf, dsize);
> +	mm_comms = select_mm_comms();

switch()/case probably looks more readable here

> +	if (mm_comms == MM_COMMS_UNDEFINED) {
> +		ret = EFI_UNSUPPORTED;
> +	} else {
> +		if (mm_comms == MM_COMMS_OPTEE)
> +			ret = optee_mm_communicate(comm_buf, dsize);
> +		else
> +			ret = ffa_mm_communicate(comm_buf, dsize);
> +	}
> +
>  	if (ret != EFI_SUCCESS) {
>  		log_err("%s failed!\n", __func__);
>  		return ret;
> @@ -258,6 +555,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
>  		goto out;
>  	}
>  	*size = var_payload->size;
> +
> +	#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> +		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
> +			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
> +				MM_VARIABLE_COMMUNICATE_SIZE;
> +	#endif
> +
>  	/*
>  	 * There seems to be a bug in EDK2 miscalculating the boundaries and
>  	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> @@ -697,7 +1001,7 @@ void efi_variables_boot_exit_notify(void)
>  		ret = EFI_NOT_FOUND;
>
>  	if (ret != EFI_SUCCESS)
> -		log_err("Unable to notify StMM for ExitBootServices\n");
> +		log_err("Unable to notify the MM partition for ExitBootServices\n");
>  	free(comm_buf);
>
>  	/*
> --
> 2.25.1
>

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 06/10] arm_ffa: introduce sandbox FF-A support
  2023-04-19  1:49                                                                                             ` Simon Glass
@ 2023-05-03 17:56                                                                                               ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-03 17:56 UTC (permalink / raw)
  To: Simon Glass; +Cc: nd, u-boot

Hi Simon,

> Hi Abdellatif,
> 
> On Wed, 12 Apr 2023 at 03:43, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > 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>
> > 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>
> > Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
> >
> > ---
> > Changelog:
> > ===============
> >
> > v11:
> >
> > * rename ffa_try_discovery() to sandbox_ffa_discover()
> > * rename sandbox_ffa_query_core_state() to sandbox_query_ffa_emul_state()
> > * store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
> > * set the emulator as parent of the sandbox FF-A device
> 
> This is close, but not quite what I expected.
> 
> I suspect the emulator should be the child of the FF-A device, not the
> parent? You should update the devicetree to show that. You should not
> need to reparent anything.
> 
> Then you put this in your FFA uclass so it binds the emulator:
> 
> .post_bind = dm_scan_fdt_dev,
> 

Thanks. Sorry for the late reply, I was in holidays.

I made few tweaks based on your suggestion and this will be in v12 patchset (work in progress).
In v12, reparenting will be removed and DT will be used to reflect the relationship between
the emulator and the FF-A device. Also, dm_scan_fdt_dev() is used to bind the child.

However, in case of FF-A the emulator should be the parent.

Please refer to the explanation below for more details.

DT nodes: (tested and works)

	arm-ffa-emul {
		compatible = "sandbox,arm-ffa-emul";

		sandbox-arm-ffa {
				compatible = "sandbox,arm-ffa";
		};
	};

In real HW, the secure side exists before the FF-A device is set up.
The FF-A device needs the secure side up and running so it can query the FF-A
framework version during FF-A discovery.

The same concept is followed in sandbox mode:

- The emulator device is the parent of the FF-A device. So, the emulator priv exists in memory before the FF-A device is bound.
   The emulator priv contains the secure side data (i.e: FF-A framework version)

- The FF-A device is the child, when bound it discovers FF-A framework by querying the version from the emulator

I hope this suggestion makes sense to you.

Cheers,
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v12 00/10] introduce Arm FF-A support
  2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                             ` (10 preceding siblings ...)
  2023-04-17 16:02                                                                                           ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-05-12 12:10                                                                                           ` Abdellatif El Khlifi
  2023-05-12 12:10                                                                                             ` [PATCH v12 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                                                                               ` (10 more replies)
  11 siblings, 11 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-12 12:10 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong, Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].

FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
communicate with each other. A partition could be a VM in the Normal or Secure world, an
application in S-EL0, or a Trusted OS in S-EL1.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

   => dm tree

    Class     Index  Probed  Driver                Name
   -----------------------------------------------------------
   ...
    firmware      0  [ + ]   psci                      |-- psci
    ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
   ...

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

This implementation of the specification provides support for Aarch64.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

    - Discover the presence of secure partitions (SPs) of interest
    - Access an SP's service through communication protocols
      (e.g: EFI MM communication protocol)

The FF-A support provides the following features:

    - Being generic by design and can be used by any Arm 64-bit platform
    - FF-A support can be compiled and used without EFI
    - Support for SMCCCv1.2 x0-x17 registers
    - Support for SMC32 calling convention
    - Support for 32-bit and 64-bit FF-A direct messaging
    - Support for FF-A MM communication (compatible with EFI boot time)
    - Enabling FF-A and MM communication in Corstone1000 platform as a use case
    - 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.
    - Sandbox FF-A test cases.
    - A new command called armffa is provided as an example of how to access the
      FF-A bus

For more details about the FF-A support please refer to [B] and refer to [C] for
how to use the armffa command.

Please find at [D] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of the major changes:
===========================

v12:

* remove the global variable (dscvry_info), use uc_priv instead
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* remove reparenting by making the sandbox emulator parent of the FF-A device in the DT
* improve argument checks for the armffa command
* address nits

v11: [11]

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* use U_BOOT_CMD_WITH_SUBCMDS for armffa command
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device
* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* use ut_asserteq_mem() in uuid_str_to_le_bin test case
* address nits

v10: [10]

* provide the FF-A driver operations through the Uclass (arm-ffa-uclass.c)
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c renamed from core.c)
* split the FF-A sandbox support into an emulator (ffa-emul-uclass.c) and a driver (sandbox_ffa.c)
* use the FF-A driver Uclass operations by clients (armffa command, tests, MM comms)
* use uclass_first_device to search and probe the FF-A device (whether it is on Arm or on sandbox)
* address nits

v9: [9]

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
* align FF-A sandbox driver with FF-A discovery through DM
* use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
* add documentation for the armffa command: doc/usage/cmd/armffa.rst
* introduce testcase for uuid_str_to_le_bin

v8: [8]

* pass the FF-A bus device to the bus operations
* isolate the compilation choices between FF-A and OP-TEE
* drop OP-TEE configs from Corstone-1000 defconfig
* make ffa_get_partitions_info() second argument to be an SP count in both
  modes

v7: [7]

* add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v6: [6]

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

List of previous patches:

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
[7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
[8]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
[9]: https://lore.kernel.org/all/20230310141016.137986-1-abdellatif.elkhlifi@arm.com/
[10]: https://lore.kernel.org/all/20230328161157.219375-1-abdellatif.elkhlifi@arm.com/
[11]: https://lore.kernel.org/all/20230412094245.44674-1-abdellatif.elkhlifi@arm.com/

More details:

[A]: https://developer.arm.com/documentation/den0077/latest/
[B]: doc/arch/arm64.ffa.rst
[C]: doc/usage/cmd/armffa.rst
[D]: example of boot logs when enabling FF-A

```
   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64

   DRAM:  2 GiB
   Arm FF-A framework discovery
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   ...
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   EFI: MM partition ID 0x8003
   ...
   EFI stub: Booting Linux Kernel...
   ...
   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
   Machine model: ARM Corstone1000 FPGA MPS3 board
```

Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (10):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce uuid_str_to_le_bin function
  lib: uuid: introduce testcase for uuid_str_to_le_bin
  arm_ffa: introduce Arm FF-A support
  arm_ffa: introduce armffa command
  arm_ffa: introduce sandbox FF-A support
  arm_ffa: introduce sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   18 +
 arch/arm/cpu/armv8/smccc-call.S               |   57 +-
 arch/arm/lib/asm-offsets.c                    |   16 +
 arch/sandbox/dts/sandbox.dtsi                 |    9 +
 arch/sandbox/dts/test.dts                     |    8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |   72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        |  121 ++
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    1 +
 cmd/armffa.c                                  |  196 +++
 configs/corstone1000_defconfig                |    2 +
 configs/sandbox64_defconfig                   |    1 +
 configs/sandbox_defconfig                     |    1 +
 doc/arch/arm64.ffa.rst                        |  270 +++++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox/sandbox.rst                  |    1 +
 doc/usage/cmd/armffa.rst                      |   93 ++
 doc/usage/index.rst                           |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   42 +
 drivers/firmware/arm-ffa/Makefile             |   16 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 drivers/firmware/arm-ffa/ffa-emul-uclass.c    |  720 +++++++++++
 drivers/firmware/arm-ffa/sandbox_ffa.c        |  110 ++
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/configs/corstone1000.h                |   15 +-
 include/dm/uclass-id.h                        |    7 +
 include/linux/arm-smccc.h                     |   45 +
 include/mm_communication.h                    |   13 +
 include/uuid.h                                |   15 +
 lib/efi_loader/Kconfig                        |   14 +-
 lib/efi_loader/efi_variable_tee.c             |  291 ++++-
 lib/uuid.c                                    |   48 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   33 +
 test/dm/Makefile                              |    3 +-
 test/dm/ffa.c                                 |  261 ++++
 test/lib/Makefile                             |    1 +
 test/lib/uuid.c                               |   41 +
 42 files changed, 4175 insertions(+), 10 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 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 doc/usage/cmd/armffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/lib/uuid.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v12 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
@ 2023-05-12 12:10                                                                                             ` Abdellatif El Khlifi
  2023-05-19 12:56                                                                                               ` Ilias Apalodimas
  2023-05-12 12:10                                                                                             ` [PATCH v12 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
                                                                                                               ` (9 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-12 12:10 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>

---

Changelog:
===============

v9:

* update the copyright string

v7:

* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

 arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
 arch/arm/lib/asm-offsets.c      | 16 +++++++++
 include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..93f66d3366 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,7 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
- */
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+*/
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
 #include <generated/asm-offsets.h>
@@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 6de0ce9152..181a8ac4c2 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,11 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * 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>
@@ -90,6 +95,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#ifdef CONFIG_ARM64
+	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..f44e9e8f93 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +74,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v12 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
  2023-05-12 12:10                                                                                             ` [PATCH v12 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-05-12 12:10                                                                                             ` Abdellatif El Khlifi
  2023-05-12 12:10                                                                                             ` [PATCH v12 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
                                                                                                               ` (8 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-12 12:10 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong

convert UUID string to little endian binary data

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
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>

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

v9:

* add a full function prototype description in uuid.h

v8:

* use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

 include/uuid.h | 15 +++++++++++++++
 lib/uuid.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..89b93e642b 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,10 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +48,15 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ * Return:
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 96e1af3c8b..45f325d964 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * 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>
@@ -354,6 +358,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16;
+	u32 tmp32;
+	u64 tmp64;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+	memcpy(uuid_bin, &tmp32, 4);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16));
+	memcpy(uuid_bin + 10, &tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v12 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
  2023-05-12 12:10                                                                                             ` [PATCH v12 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2023-05-12 12:10                                                                                             ` [PATCH v12 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2023-05-12 12:10                                                                                             ` Abdellatif El Khlifi
  2023-05-12 12:10                                                                                             ` [PATCH v12 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                               ` (7 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-12 12:10 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong

provide a test case

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Simon Glass <sjg@chromium.org>

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

v11:

* use ut_asserteq_mem()

 MAINTAINERS       |  5 +++++
 test/lib/Makefile |  1 +
 test/lib/uuid.c   | 41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)
 create mode 100644 test/lib/uuid.c

diff --git a/MAINTAINERS b/MAINTAINERS
index c8f72e9ec6..926c7201a5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1634,3 +1634,8 @@ S:	Maintained
 F:	arch/arm/dts/ls1021a-twr-u-boot.dtsi
 F:	drivers/crypto/fsl/
 F:	include/fsl_sec.h
+
+UUID testing
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	test/lib/uuid.c
diff --git a/test/lib/Makefile b/test/lib/Makefile
index e0bd9e04e8..e75a263e6a 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_AES) += test_aes.o
 obj-$(CONFIG_GETOPT) += getopt.o
 obj-$(CONFIG_CRC8) += test_crc8.o
 obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o
+obj-$(CONFIG_LIB_UUID) += uuid.o
 else
 obj-$(CONFIG_SANDBOX) += kconfig_spl.o
 endif
diff --git a/test/lib/uuid.c b/test/lib/uuid.c
new file mode 100644
index 0000000000..e24331a136
--- /dev/null
+++ b/test/lib/uuid.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <uuid.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* test UUID */
+#define TEST_SVC_UUID	"ed32d533-4209-99e6-2d72-cdd998a79cc0"
+
+#define UUID_SIZE 16
+
+/* The UUID binary data (little-endian format) */
+static const u8 ref_uuid_bin[UUID_SIZE] = {
+	0x33, 0xd5, 0x32, 0xed,
+	0x09, 0x42, 0xe6, 0x99,
+	0x72, 0x2d, 0xc0, 0x9c,
+	0xa7, 0x98, 0xd9, 0xcd
+};
+
+static int lib_test_uuid_to_le(struct unit_test_state *uts)
+{
+	const char *uuid_str = TEST_SVC_UUID;
+	u8 ret_uuid_bin[UUID_SIZE] = {0};
+
+	ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin));
+	ut_asserteq_mem(ref_uuid_bin, ret_uuid_bin, UUID_SIZE);
+
+	return 0;
+}
+
+LIB_TEST(lib_test_uuid_to_le, 0);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v12 04/10] arm_ffa: introduce Arm FF-A support
  2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
                                                                                                               ` (2 preceding siblings ...)
  2023-05-12 12:10                                                                                             ` [PATCH v12 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-05-12 12:10                                                                                             ` Abdellatif El Khlifi
  2023-05-12 12:10                                                                                             ` [PATCH v12 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                                                                               ` (6 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-12 12:10 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong, Heinrich Schuchardt

Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- ffa_partition_info_get
- ffa_sync_send_receive
- ffa_rxtx_unmap

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 please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

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

v12:

* remove dscvry_info
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* address nits

v11:

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* pass dev as an argument of arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* add emul field in struct ffa_discovery_info
* address nits

v10:

* provide the driver operations through the Uclass
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c)
* rename core.c to arm-ffa.c
* address nits

v9:

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding

v8:

* make ffa_get_partitions_info() second argument to be an SP count in both
  modes
* update ffa_bus_prvdata_get() to return a pointer rather than a pointer
  address
* remove packing from ffa_partition_info and ffa_send_direct_data structures
* pass the FF-A bus device to the bus operations

v7:

* add support for 32-bit direct messaging
* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* improve the declaration of error handling mapping
* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the U-Boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the U-Boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

 MAINTAINERS                                   |    8 +
 doc/arch/arm64.ffa.rst                        |  247 ++++
 doc/arch/index.rst                            |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   36 +
 drivers/firmware/arm-ffa/Makefile             |    8 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |   14 +
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/dm/uclass-id.h                        |    6 +
 13 files changed, 1950 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 926c7201a5..4e285f88cb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,6 +266,14 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+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>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..7719215cdf
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,247 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Support
+================
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
+communicate with each other. A partition could be a VM in the Normal or Secure world, an
+application in S-EL0, or a Trusted OS in S-EL1.
+
+The U-Boot FF-A support (the bus) implements the interfaces to communicate
+with partitions in the Secure world aka Secure partitions (SPs).
+
+The FF-A support specifically focuses on communicating with SPs that
+isolate portions of EFI runtime services that must run in a protected
+environment which is inaccessible by the Host OS or Hypervisor.
+Examples of such services are set/get variables.
+
+The FF-A support uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+At this stage of development only EFI boot-time services are supported.
+Runtime support will be added in future developments.
+
+The U-Boot FF-A support provides the following parts:
+
+- A Uclass driver providing generic FF-A methods.
+- An Arm FF-A device driver providing Arm-specific methods and reusing the Uclass methods.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the U-Boot FF-A support relies on
+`FF-A v1.0 specification`_ and uses SMC32 calling convention which
+means using the first 32-bit data of the Xn registers.
+
+At this stage we only need the FF-A v1.0 features.
+
+The FF-A support has been tested with OP-TEE which supports SMC32 calling
+convention.
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A support uses 64-bit registers as per `SMC Calling Convention v1.2 specification`_.
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+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.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers.
+Then, an SMC instruction is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-Boot Arm FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs.
+
+FF-A bus discovery on Arm 64-bit platforms
+---------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
+an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
+This discovery mechanism is performed by the PSCI driver.
+
+The PSCI driver comes with a PSCI device tree node which is the root node for all
+architecture features including FF-A bus.
+
+::
+
+   => dm tree
+
+    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.
+
+In case of FF-A, the callback is arm_ffa_is_supported() which tries to discover the
+FF-A framework by querying the FF-A framework version from secure world using
+FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
+mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver
+with the device using device_bind_driver().
+
+At this stage the FF-A bus is registered with the DM and can be interacted with using
+the DM APIs.
+
+Clients are able to probe then use the FF-A bus by calling uclass_first_device().
+Please refer to the armffa command implementation as an example of how to probe
+and interact with the FF-A bus.
+
+When calling uclass_first_device(), the FF-A driver is probed and ends up calling
+ffa_do_probe() provided by the Uclass which does the following:
+
+    - saving the FF-A framework version in uc_priv
+    - querying from secure world the u-boot endpoint ID
+    - querying from secure world the supported features of FFA_RXTX_MAP
+    - mapping the RX/TX buffers
+    - querying from secure world all the partitions information
+
+When one of the above actions fails, probing fails and the driver stays not active
+and can be probed again if needed.
+
+FF-A device destruction
+-------------------------
+
+When the FF-A device is removed by the DM, RX/TX buffers are automatically
+unmapped and freed.
+
+For example, at EFI efi_exit_boot_services() active devices are automatically removed
+by dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL).
+
+By consequence, the FF-A RX/TX are unmapped automatically.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must query the SPs they are looking for
+during EFI boot-time mode using the service UUID.
+
+The RX/TX buffers are only available at EFI boot-time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped before EFI runtime mode starts.
+The driver provides a bus operation for that called ffa_rxtx_unmap() and this is done
+automatically at efi_exit_boot_services().
+
+The Linux kernel allocates its own RX/TX buffers. To be able to register these kernel buffers
+with secure world, the U-Boot's RX/TX buffers should be unmapped before EFI runtime starts.
+
+When invoking FF-A direct messaging, clients should specify which ABI protocol
+they want to use (32-bit vs 64-bit). Selecting the protocol means using
+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
+The calling convention between U-Boot and the secure world stays the same: SMC32.
+
+Requirements for user drivers
+-------------------------------------
+
+Users who want to implement their custom FF-A device driver while reusing the FF-A Uclass can do so
+by implementing their own invoke_ffa_fn() in the user driver.
+
+The bus driver layer
+------------------------------
+
+FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c
+
+The following features are provided:
+
+- Support for the 32-bit version of the following ABIs:
+
+    - FFA_VERSION
+    - FFA_ID_GET
+    - FFA_FEATURES
+    - FFA_PARTITION_INFO_GET
+    - FFA_RXTX_UNMAP
+    - FFA_RX_RELEASE
+    - FFA_RUN
+    - FFA_ERROR
+    - FFA_SUCCESS
+    - FFA_INTERRUPT
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Support for the 64-bit version of the following ABIs:
+
+    - FFA_RXTX_MAP
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, FF-A support takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- FF-A support provides driver operations to be used by upper layers:
+
+    - ffa_partition_info_get
+    - ffa_sync_send_receive
+    - ffa_rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+Example of boot logs with FF-A enabled
+--------------------------------------
+
+For example, when using FF-A with Corstone-1000 the logs are as follows:
+
+::
+
+   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64
+
+   DRAM:  2 GiB
+   Arm FF-A framework discovery
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   ...
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   EFI: MM partition ID 0x8003
+   ...
+   EFI stub: Booting Linux Kernel...
+   ...
+   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
+   Machine model: ARM Corstone1000 FPGA MPS3 board
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+
+.. _`FF-A v1.0 specification`: https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e
+.. _`SMC Calling Convention v1.2 specification`: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index b8da4b8c8e..2f916f4026 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Makefile b/drivers/Makefile
index 29be78a3f2..6094fac50d 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -114,6 +114,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index eae1c8ddc9..8789b1ea14 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
 	  the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
 	  services if any and reported as supported by the SMCCC firmware.
 
+source "drivers/firmware/arm-ffa/Kconfig"
 source "drivers/firmware/scmi/Kconfig"
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..9200c8028b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select ARM_SMCCC_FEATURES
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
+	  FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
+	  by the PSCI driver.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  The FF-A support on U-Boot  takes care of all the interactions between Normal
+	  world and Secure World.
+
+	  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
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..11b1766285
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,8 @@
+# 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>
+
+obj-y += arm-ffa-uclass.o arm-ffa.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..ffa9d81fa7
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,1065 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	[NOT_SUPPORTED] = -EOPNOTSUPP,
+	[INVALID_PARAMETERS] = -EINVAL,
+	[NO_MEMORY] = -ENOMEM,
+	[BUSY] = -EBUSY,
+	[INTERRUPTED] = -EINTR,
+	[DENIED] = -EACCES,
+	[RETRY] = -EAGAIN,
+	[ABORTED] = -ECANCELED,
+};
+
+static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			[NO_MEMORY] =
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			[BUSY] =
+			"BUSY: RX buffer of the caller is not free",
+			[DENIED] =
+			"DENIED: Callee is not in a state to handle this request",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			[DENIED] =
+			"DENIED: Caller did not have ownership of the RX buffer",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			[NO_MEMORY] =
+			"NO_MEMORY: Not enough memory",
+			[DENIED] =
+			"DENIED: Buffer pair already registered",
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno() - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+static int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* Map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+static int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* Map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	log_err("%s\n", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/* FF-A ABIs implementation (U-Boot side) */
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void __weak invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+}
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	log_info("FF-A driver %d.%d\nFF-A framework %d.%d\n",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) {
+		log_info("FF-A versions are compatible\n");
+
+		if (dev) {
+			uc_priv = dev_get_uclass_priv(dev);
+			if (uc_priv)
+				uc_priv->fwk_version = res.a0;
+		}
+
+		return 0;
+	}
+
+	log_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id() - FFA_ID_GET handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		uc_priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		log_debug("FF-A endpoint ID is %u\n", uc_priv->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt() - set the minimum number of pages in each of the RX/TX buffers
+ * @dev: The FF-A bus device
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * Set the minimum number of pages in each of the RX/TX buffers in uc_priv
+ *
+ * Return:
+ *
+ * rxtx_min_pages field contains the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	switch (prop_field) {
+	case RXTX_4K:
+		uc_priv->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		uc_priv->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		uc_priv->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		log_err("RX/TX buffer size not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features_hdlr() - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_FEATURES FF-A function to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers() - free the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Free the RX/TX buffers
+ */
+static void ffa_free_rxtx_buffers(struct udevice *dev)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Freeing FF-A RX/TX buffers\n");
+
+	if (uc_priv->pair.rxbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+	}
+
+	if (uc_priv->pair.txbuf) {
+		free(uc_priv->pair.txbuf);
+		uc_priv->pair.txbuf = NULL;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers() - allocate the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ * The size of the memory allocated is the minimum allowed.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(struct udevice *dev)
+{
+	u64 bytes;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Using %lu 4KB page(s) for FF-A RX/TX buffers size\n",
+		  uc_priv->pair.rxtx_min_pages);
+
+	bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 * Assumption: Memory allocated with memalign is always physically contiguous
+	 */
+
+	uc_priv->pair.rxbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.rxbuf) {
+		log_err("failure to allocate RX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A RX buffer at virtual address %p\n", uc_priv->pair.rxbuf);
+
+	uc_priv->pair.txbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.txbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+		log_err("failure to allocate the TX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A TX buffer at virtual address %p\n", uc_priv->pair.txbuf);
+
+	/* Make sure the buffers are cleared before use */
+	memset(uc_priv->pair.rxbuf, 0, bytes);
+	memset(uc_priv->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers_hdlr() - FFA_RXTX_MAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_MAP FF-A function to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	ret = ffa_alloc_rxtx_buffers(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 * no need to convert from virtual to physical
+	 */
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = map_to_sysmem(uc_priv->pair.txbuf),
+			.a2 = map_to_sysmem(uc_priv->pair.rxbuf),
+			.a3 = uc_priv->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		log_debug("FF-A RX/TX buffers mapped\n");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers(dev);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_UNMAP FF-A function to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	log_debug("unmapping FF-A RX/TX buffers\n");
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers(dev);
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer_hdlr() - FFA_RX_RELEASE handler function
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_RX_RELEASE FF-A function to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical() - check whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * Used by ffa_read_partitions_info to search for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+static bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+				   const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info() - read queried partition data
+ * @dev: The FF-A bus device
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * Read the partitions information returned by the FFA_PARTITION_INFO_GET and saves it in uc_priv
+ *
+ * Return:
+ *
+ * uc_priv is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(struct udevice *dev, u32 count,
+				    struct ffa_partition_uuid *part_uuid)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	if (!count) {
+		log_err("no partition detected\n");
+		return -ENODATA;
+	}
+
+	log_debug("Reading FF-A partitions data from the RX buffer\n");
+
+	if (!part_uuid) {
+		/* Querying information of all partitions */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			log_err("partitions data size exceeds the RX buffer size:\n");
+			log_err("    sizes in bytes: data %llu , RX buffer %llu\n",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		uc_priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO);
+		if (!uc_priv->partitions.descs) {
+			log_err("cannot  allocate partitions data buffer\n");
+			return -ENOMEM;
+		}
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			uc_priv->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			log_debug("FF-A partition ID %x : info cached\n",
+				  uc_priv->partitions.descs[desc_idx].info.id);
+		}
+
+		uc_priv->partitions.count = count;
+
+		log_debug("%d FF-A partition(s) found and cached\n", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		/*
+		 * Search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/* Search the current ID in the cached partitions */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < uc_priv->partitions.count;
+			     cached_desc_idx++) {
+				/* Save the UUID */
+				if (uc_priv->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					uc_priv->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info() - invoke FFA_PARTITION_INFO_GET and save partitions data
+ * @dev: The FF-A bus device
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * Execute the FFA_PARTITION_INFO_GET to query the partitions data.
+ * Then, call ffa_read_partitions_info to save the data in uc_priv.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid);
+			if (ret) {
+				log_err("failed reading SP(s) data , err (%d)\n", ret);
+				ffa_release_rx_buffer_hdlr(dev);
+				return -EINVAL;
+			}
+		}
+
+		/* Return the SP count (when querying using a UUID) */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer_hdlr(dev);
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET FF-A function to query the partition information
+ * from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * If the partition(s) matching the UUID found, the partition(s) information and the
+ * number are returned.
+ * If no partition matching the UUID is found in the cached area, a new FFA_PARTITION_INFO_GET
+ * call is issued.
+ * If not done yet, the UUID is updated in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	u32 i;
+	struct ffa_partition_uuid part_uuid = {0};
+	struct ffa_priv *uc_priv;
+	struct ffa_partition_desc *rx_descs;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs) {
+		log_err("no partition installed\n");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		log_err("no UUID provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_count) {
+		log_err("no count argument provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_descs) {
+		log_err("no info argument provided\n");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		log_err("invalid UUID\n");
+		return -EINVAL;
+	}
+
+	log_debug("Searching FF-A partitions using the provided UUID\n");
+
+	*sp_count = 0;
+	*sp_descs = uc_priv->pair.rxbuf;
+	rx_descs = *sp_descs;
+
+	/* Search in the cached partitions */
+	for (i = 0; i < uc_priv->partitions.count; i++)
+		if (ffa_uuid_are_identical(&uc_priv->partitions.descs[i].sp_uuid,
+					   &part_uuid)) {
+			log_debug("FF-A partition ID %x matches the provided UUID\n",
+				  uc_priv->partitions.descs[i].info.id);
+
+			(*sp_count)++;
+			*rx_descs++ = uc_priv->partitions.descs[i];
+			}
+
+	if (!(*sp_count)) {
+		int ret;
+
+		log_debug("No FF-A partition found. Querying framework ...\n");
+
+		ret = ffa_query_partitions_info(dev, &part_uuid, sp_count);
+
+		if (!ret) {
+			log_debug("Number of FF-A partition(s) matching the UUID: %d\n", *sp_count);
+
+			if (*sp_count)
+				ret = ffa_get_partitions_info_hdlr(dev, uuid_str, sp_count,
+								   sp_descs);
+			else
+				ret = -ENODATA;
+		}
+
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info() - Query and saves all secure partitions data
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_PARTITION_INFO_GET FF-A function to query from secure world
+ * all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in uc_priv
+ * and we keep the UUID field empty (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * Called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(struct udevice *dev)
+{
+	return ffa_query_partitions_info(dev, NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Implement FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u64 req_mode, resp_mode;
+	struct ffa_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* No partition installed */
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs)
+		return -ENODEV;
+
+	if (is_smc64) {
+		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+	} else {
+		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = req_mode,
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == resp_mode) {
+		/* Message sent with response extract the return data */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/* FF-A driver operations (used by clients for communicating with FF-A)*/
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Driver operation for FFA_PARTITION_INFO_GET.
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->partition_info_get)
+		return -ENOSYS;
+
+	return ops->partition_info_get(dev, uuid_str, sp_count, sp_descs);
+}
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Driver operation for FFA_MSG_SEND_DIRECT_{REQ,RESP}.
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->sync_send_receive)
+		return -ENOSYS;
+
+	return ops->sync_send_receive(dev, dst_part_id, msg, is_smc64);
+}
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * @dev: The FF-A bus device
+ *
+ * Driver operation for FFA_RXTX_UNMAP.
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_rxtx_unmap(struct udevice *dev)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->rxtx_unmap)
+		return -ENOSYS;
+
+	return ops->rxtx_unmap(dev);
+}
+
+/**
+ * ffa_do_probe() - probing FF-A framework
+ * @dev:	the FF-A bus device (arm_ffa)
+ *
+ * Probing is triggered on demand by clients searching for the uclass.
+ * At probe level the following actions are done:
+ *	- saving the FF-A framework version in uc_priv
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in uc_priv.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_do_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_endpoint_id(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_cache_partitions_info(dev);
+	if (ret) {
+		ffa_unmap_rxtx_buffers_hdlr(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+UCLASS_DRIVER(ffa) = {
+	.name			= "ffa",
+	.id			= UCLASS_FFA,
+	.pre_probe		= ffa_do_probe,
+	.pre_remove		= ffa_unmap_rxtx_buffers_hdlr,
+	.per_device_auto	= sizeof(struct ffa_priv)
+};
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
new file mode 100644
index 0000000000..68df75bd9e
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -0,0 +1,104 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <linux/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * 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 low level SMC assembly function
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * arm_ffa_discover() - perform FF-A discovery
+ * @dev: The Arm FF-A bus device (arm_ffa)
+ * 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:
+ *
+ * true on success. Otherwise, false.
+ */
+static bool arm_ffa_discover(struct udevice *dev)
+{
+	int ret;
+
+	log_info("Arm FF-A framework discovery\n");
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/**
+ * arm_ffa_is_supported() - FF-A bus discovery callback
+ * @invoke_fn: legacy SMC invoke function (not used)
+ *
+ * Perform FF-A discovery by calling arm_ffa_discover().
+ * Discovery is performed by querying the FF-A framework version from
+ * secure world using the FFA_VERSION ABI.
+ *
+ * The FF-A driver is registered as an SMCCC feature driver. So, features discovery
+ * callbacks are called by the PSCI driver (PSCI device is the SMCCC features
+ * root device).
+ *
+ * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
+ * So, the legacy SMC invocation is not used.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static bool arm_ffa_is_supported(void (*invoke_fn)(ulong a0, ulong a1,
+						   ulong a2, ulong a3,
+						   ulong a4, ulong a5,
+						   ulong a6, ulong a7,
+						   struct arm_smccc_res *res))
+{
+	return arm_ffa_discover(NULL);
+}
+
+/* Arm FF-A driver operations */
+
+static const struct ffa_bus_ops 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,
+};
+
+/* Registering the FF-A driver as an SMCCC feature driver */
+
+ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
+	.driver_name = FFA_DRV_NAME,
+	.is_supported = arm_ffa_is_supported,
+};
+
+/* Declaring the FF-A driver under UCLASS_FFA */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.flags		= DM_REMOVE_OS_PREPARE,
+	.ops		= &ffa_ops,
+};
diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
new file mode 100644
index 0000000000..4338f9c9b1
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
@@ -0,0 +1,14 @@
+/* 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/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..db9b1be995
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,213 @@
+/* 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 __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
+ * @a1-4:	32-bit words access to the UUID data
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct ffa_send_direct_data {
+	ulong data0; /* w3/x3 */
+	ulong data1; /* w4/x4 */
+	ulong data2; /* w5/x5 */
+	ulong data3; /* w6/x6 */
+	ulong data4; /* w7/x7 */
+};
+
+struct udevice;
+
+/**
+ * struct ffa_bus_ops - Operations for FF-A
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
+				  u32 *sp_count, struct ffa_partition_desc **sp_descs);
+	int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg,
+				 bool is_smc64);
+	int (*rxtx_unmap)(struct udevice *dev);
+};
+
+#define ffa_get_ops(dev)        ((struct ffa_bus_ops *)(dev)->driver->ops)
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ */
+int ffa_rxtx_unmap(struct udevice *dev);
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The arm_ffa bus device
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev);
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The arm_ffa bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+struct ffa_priv;
+
+/**
+ * ffa_set_smc_conduit() - Set the SMC conduit
+ * @dev: The FF-A bus device
+ *
+ * Selects the SMC conduit by setting the FF-A ABI invoke function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_set_smc_conduit(struct udevice *dev);
+
+#endif
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
new file mode 100644
index 0000000000..d564c33c64
--- /dev/null
+++ b/include/arm_ffa_priv.h
@@ -0,0 +1,246 @@
+/* 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 __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <mapmem.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+
+/* This header is exclusively used by the FF-A Uclass and FF-A driver(s) */
+
+/* Arm FF-A driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* The FF-A SMC function definitions */
+
+#if CONFIG_IS_ENABLED(SANDBOX)
+
+/* Providing Arm SMCCC declarations to sandbox */
+
+/**
+ * struct sandbox_smccc_1_2_regs - emulated SMC call arguments or results
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct sandbox_smccc_1_2_regs {
+	ulong a0;
+	ulong a1;
+	ulong a2;
+	ulong a3;
+	ulong a4;
+	ulong a5;
+	ulong a6;
+	ulong a7;
+	ulong a8;
+	ulong a9;
+	ulong a10;
+	ulong a11;
+	ulong a12;
+	ulong a13;
+	ulong a14;
+	ulong a15;
+	ulong a16;
+	ulong a17;
+};
+
+typedef struct sandbox_smccc_1_2_regs ffa_value_t;
+
+#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))
+
+#else
+/* CONFIG_ARM64 */
+#include <linux/arm-smccc.h>
+typedef struct arm_smccc_1_2_regs ffa_value_t;
+#endif
+
+/* Defining the function pointer type for the function executing the FF-A ABIs */
+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)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR                 = 0x60,
+	FFA_SUCCESS               = 0x61,
+	FFA_INTERRUPT             = 0x62,
+	FFA_VERSION               = 0x63,
+	FFA_FEATURES              = 0x64,
+	FFA_RX_RELEASE            = 0x65,
+	FFA_RXTX_MAP              = 0x66,
+	FFA_RXTX_UNMAP            = 0x67,
+	FFA_PARTITION_INFO_GET    = 0x68,
+	FFA_ID_GET                = 0x69,
+	FFA_RUN                   = 0x6d,
+	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
+	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
+
+	/* To be updated when adding new FFA IDs */
+	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
+	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
+};
+
+enum ffa_abi_errcode {
+	NOT_SUPPORTED = 1,
+	INVALID_PARAMETERS,
+	NO_MEMORY,
+	BUSY,
+	INTERRUPTED,
+	DENIED,
+	RETRY,
+	ABORTED,
+	MAX_NUMBER_FFA_ERR
+};
+
+extern int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR];
+
+/* Container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Hosts the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	void *rxbuf; /* Virtual address returned by memalign */
+	void *txbuf; /* Virtual address returned by memalign */
+	size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */
+};
+
+struct ffa_partition_desc;
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * Contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* Virtual address */
+};
+
+/**
+ * struct ffa_priv - the driver private data structure
+ *
+ * @fwk_version:	FF-A framework version
+ * @emul:	FF-A sandbox emulator
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ *
+ * The device private data structure containing all the
+ * data read from secure world.
+ */
+struct ffa_priv {
+	u32 fwk_version;
+	struct udevice *emul;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+};
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev);
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 307ad6931c..3c6af2e3d2 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,11 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -57,6 +62,7 @@ enum uclass_id {
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_EXTCON,		/* External Connector Class */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v12 05/10] arm_ffa: introduce armffa command
  2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
                                                                                                               ` (3 preceding siblings ...)
  2023-05-12 12:10                                                                                             ` [PATCH v12 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-05-12 12:10                                                                                             ` Abdellatif El Khlifi
  2023-05-12 12:10                                                                                             ` [PATCH v12 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
                                                                                                               ` (5 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-12 12:10 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong, Heinrich Schuchardt

Provide armffa command showcasing the use of the U-Boot FF-A support

armffa is a command showcasing how to invoke FF-A operations.
This provides a guidance to the client developers on how to
call the FF-A bus interfaces. The command also allows to gather secure
partitions information and ping these  partitions. The command is also
helpful in testing the communication with secure partitions.

For more details please refer to the command documentation [1].

[1]: doc/usage/cmd/armffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

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

v12:

* add subcommands argument checks
* usage documentation: update command return codes
* remove calloc when querying SPs
* address nits

v11:

* use U_BOOT_CMD_WITH_SUBCMDS
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* address nits

v9:

* remove manual FF-A discovery and use DM
* use DM class APIs to probe and interact with the FF-A bus
* add doc/usage/cmd/armffa.rst

v8:

* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* adapt do_ffa_dev_list() following the recent update on
  uclass_first_device/uclass_next_device functions (they return void now)
* set armffa command to use 64-bit direct messaging

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

 MAINTAINERS                      |   2 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   1 +
 cmd/armffa.c                     | 196 +++++++++++++++++++++++++++++++
 doc/arch/arm64.ffa.rst           |   7 ++
 doc/usage/cmd/armffa.rst         |  93 +++++++++++++++
 doc/usage/index.rst              |   1 +
 drivers/firmware/arm-ffa/Kconfig |   1 +
 8 files changed, 311 insertions(+)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/usage/cmd/armffa.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 4e285f88cb..40c356e539 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,7 +269,9 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+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
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 65957da7f5..82f03d1f00 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -934,6 +934,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the FF-A support
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index 6c37521b4e..7d20a85a46 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,7 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_2048) += 2048.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..fa268e9cb9
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,196 @@
+// 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 <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+#include <asm/io.h>
+
+/**
+ * ffa_get_dev() - Return the FF-A device
+ * @devp:	pointer to the FF-A device
+ *
+ * Search for the FF-A device.
+ *
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_dev(struct udevice **devp)
+{
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, devp);
+	if (ret) {
+		log_err("Cannot find FF-A bus device\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * do_ffa_getpart() - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver
+ * partition_info_get operation which implements FFA_PARTITION_INFO_GET
+ * ABI to retrieve the data. The input UUID string is expected to be in big
+ * endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	u32 i;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+
+	ret = ffa_partition_info_get(dev, argv[1], &count, &descs);
+	if (ret) {
+		log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	/* SPs found , show the partition information */
+	for (i = 0; i < count ; i++) {
+		log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
+			 descs[i].info.id,
+			 descs[i].info.exec_ctxt,
+			 descs[i].info.properties);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_ffa_ping() - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Send data to the secure partition which the ID is provided
+ * as an argument. Use the arm_ffa driver sync_send_receive operation
+ * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	errno = 0;
+	part_id = strtoul(argv[1], NULL, 16);
+
+	if (errno) {
+		log_err("Invalid partition ID\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	if (!ret) {
+		u8 cnt;
+
+		log_info("SP response:\n[LSB]\n");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			log_info("%llx\n", ((u64 *)&msg)[cnt]);
+		return CMD_RET_SUCCESS;
+	}
+
+	log_err("Sending direct request error (%d)\n", ret);
+	return CMD_RET_FAILURE;
+}
+
+/**
+ *do_ffa_devlist() - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query the device belonging to the UCLASS_FFA
+ * class.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	log_info("device name %s, dev %p, driver name %s, ops %p\n",
+		 dev->name,
+		(void *)map_to_sysmem(dev),
+		 dev->driver->name,
+		 (void *)map_to_sysmem(dev->driver->ops));
+
+	return CMD_RET_SUCCESS;
+}
+
+static char armffa_help_text[] =
+	"getpart <partition UUID>\n"
+	"       - lists the partition(s) info\n"
+	"ping <partition ID>\n"
+	"       - sends a data pattern to the specified partition\n"
+	"devlist\n"
+	"       - displays information about the FF-A device/driver\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
+			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
+			U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping),
+			U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist));
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 7719215cdf..c7fca0f103 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -214,6 +214,13 @@ The following features are provided:
 
 - FF-A bus can be compiled and used without EFI
 
+The armffa command
+-----------------------------------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke the driver operations.
+
+Please refer the command documentation at :doc:`../usage/cmd/armffa`
+
 Example of boot logs with FF-A enabled
 --------------------------------------
 
diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
new file mode 100644
index 0000000000..3d422686c1
--- /dev/null
+++ b/doc/usage/cmd/armffa.rst
@@ -0,0 +1,93 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+armffa command
+==============
+
+Synopsis
+--------
+
+::
+
+   armffa [sub-command] [arguments]
+
+   sub-commands:
+
+        getpart [partition UUID]
+
+            lists the partition(s) info
+
+        ping [partition ID]
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays information about the FF-A device/driver
+
+Description
+-----------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
+
+The command also allows to gather secure partitions information and ping these  partitions.
+
+The command is also helpful in testing the communication with secure partitions.
+
+Example
+-------
+
+The following examples are run on Corstone-1000 platform.
+
+* ping
+
+::
+
+   corstone1000# armffa ping 0x8003
+   SP response:
+   [LSB]
+   fffffffe
+   0
+   0
+   0
+   0
+
+* ping (failure case)
+
+::
+
+   corstone1000# armffa ping 0
+   Sending direct request error (-22)
+
+* getpart
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
+   Partition: id = 8003 , exec_ctxt 1 , properties 3
+
+* getpart (failure case)
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221
+   INVALID_PARAMETERS: Unrecognized UUID
+   Failure in querying partitions count (error code: -22)
+
+* devlist
+
+::
+
+   corstone1000# armffa devlist
+   device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98
+
+Configuration
+-------------
+
+The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
+
+Return value
+------------
+
+The return value $? is 0 (true) on success, 1 (false) on failure.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 0fde130a54..3115ca4aff 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -22,6 +22,7 @@ Shell commands
 
    cmd/acpi
    cmd/addrmap
+   cmd/armffa
    cmd/askenv
    cmd/base
    cmd/bdinfo
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index 9200c8028b..a7d5392859 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
 	depends on DM && ARM64
 	select ARM_SMCCC
 	select ARM_SMCCC_FEATURES
+	imply CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v12 06/10] arm_ffa: introduce sandbox FF-A support
  2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
                                                                                                               ` (4 preceding siblings ...)
  2023-05-12 12:10                                                                                             ` [PATCH v12 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-05-12 12:10                                                                                             ` Abdellatif El Khlifi
  2023-05-12 12:10                                                                                             ` [PATCH v12 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                                                                               ` (4 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-12 12:10 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong, Heinrich Schuchardt

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>
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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

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

v12:

* remove reparenting by making the emulator parent of the FF-A device in the DT
* add invoke_ffa_fn()
* address nits

v11:

* rename ffa_try_discovery() to sandbox_ffa_discover()
* rename sandbox_ffa_query_core_state() to sandbox_query_ffa_emul_state()
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device

v10:

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

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

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

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

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

v1: introduce the sandbox driver

 MAINTAINERS                                   |   3 +-
 arch/sandbox/dts/sandbox.dtsi                 |   9 +
 arch/sandbox/dts/test.dts                     |   8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |  72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        | 121 +++
 configs/sandbox64_defconfig                   |   1 +
 configs/sandbox_defconfig                     |   1 +
 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, 1081 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 40c356e539..598644bb00 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 453e53db71..7188ac1f46 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1820,6 +1820,14 @@
 	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 f3002de857..5ed2540a0e 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -261,3 +261,4 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 1ec44d5b33..8269bec879 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -344,3 +344,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index c7fca0f103..54c5b11f3b 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.
@@ -214,6 +217,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


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v12 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA
  2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
                                                                                                               ` (5 preceding siblings ...)
  2023-05-12 12:10                                                                                             ` [PATCH v12 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
@ 2023-05-12 12:10                                                                                             ` Abdellatif El Khlifi
  2023-05-12 12:10                                                                                             ` [PATCH v12 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                                                                               ` (3 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-12 12:10 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong, Heinrich Schuchardt

Add functional test cases for the FF-A support

These tests rely on the FF-A sandbox emulator and FF-A
sandbox driver which help in inspecting the FF-A communication.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

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

v12:

* remove use of dscvry_info
* drop use of calloc when querying SPs
* address nits

v11:

* drop unmapping test (taken care of by the DM when removing the device)
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT
* address nits

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

v8:

  * update partition_info_get() second argument to be an SP count
  * pass NULL device pointer to the FF-A bus discovery and operations

v7: set the tests to use 64-bit direct messaging

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

v1: introduce sandbox tests

 MAINTAINERS            |   1 +
 doc/arch/arm64.ffa.rst |   1 +
 test/dm/Makefile       |   3 +-
 test/dm/ffa.c          | 261 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 265 insertions(+), 1 deletion(-)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 598644bb00..1c81728b15 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 54c5b11f3b..577603870c 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -37,6 +37,7 @@ The U-Boot FF-A support provides the following parts:
   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.
+- Sandbox FF-A test cases.
 
 FF-A and SMC specifications
 -------------------------------------------
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 3799b1ae8f..7ed00733c1 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
-# Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -92,6 +92,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..6912666bb4
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <console.h>
+#include <dm.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <asm/sandbox_arm_ffa_priv.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Functional tests for the UCLASS_FFA */
+
+static int check_fwk_version(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	struct ffa_sandbox_data func_data;
+	u32 fwk_version = 0;
+
+	func_data.data0 = &fwk_version;
+	func_data.data0_size = sizeof(fwk_version);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_VERSION, &func_data));
+	ut_asserteq(uc_priv->fwk_version, fwk_version);
+
+	return 0;
+}
+
+static int check_endpoint_id(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_asserteq(0, uc_priv->id);
+
+	return 0;
+}
+
+static int check_rxtxbuf(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assertnonnull(uc_priv->pair.rxbuf);
+	ut_assertnonnull(uc_priv->pair.txbuf);
+
+	return 0;
+}
+
+static int check_features(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assert(uc_priv->pair.rxtx_min_pages == RXTX_4K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_16K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_64K);
+
+	return 0;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+		ut_asserteq(1, rxbuf_mapped);
+		break;
+	case FFA_RXTX_UNMAP:
+		ut_asserteq(0, rxbuf_mapped);
+		break;
+	default:
+		ut_assert(false);
+	}
+
+	return 0;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	ut_asserteq(0, rxbuf_owned);
+
+	return 0;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg;
+	u8 cnt;
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]);
+
+	return 0;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct unit_test_state *uts)
+{
+	struct ffa_partition_desc *descs;
+	u32 count, i, j, valid_sps = 0;
+	struct udevice *dev;
+	struct ffa_sandbox_data func_data;
+	struct ffa_partitions *partitions;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get from the driver the count and information of the SPs matching the UUID */
+	ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, &descs));
+
+	/* Make sure the count is correct */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+
+	/* SPs found , verify the partitions information */
+
+	func_data.data0 = &partitions;
+	func_data.data0_size = sizeof(struct ffa_partitions *);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_PARTITION_INFO_GET, &func_data));
+
+	for (i = 0; i < count ; i++) {
+		for (j = 0;
+		     j < partitions->count;
+		     j++) {
+			if (descs[i].info.id ==
+			   partitions->descs[j].info.id) {
+				valid_sps++;
+				ut_asserteq_mem(&descs[i],
+						&partitions->descs[j],
+						sizeof(struct ffa_partition_desc));
+				/* Send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(descs[i].info.id, uts);
+			}
+		}
+	}
+
+	/* Verify expected partitions found in the emulated secure world */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, valid_sps);
+
+	return 0;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	struct ffa_sandbox_data func_data;
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	struct udevice *dev;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Test FFA_VERSION */
+	check_fwk_version(uc_priv, uts);
+
+	/* Test FFA_ID_GET */
+	check_endpoint_id(uc_priv, uts);
+
+	/* Test FFA_FEATURES */
+	check_features(uc_priv, uts);
+
+	/*  Test RX/TX buffers */
+	check_rxtxbuf(uc_priv, uts);
+
+	/* Test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	sandbox_query_ffa_emul_state(FFA_RXTX_MAP, &func_data);
+	check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc1_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data);
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc2_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data));
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg;
+	int ret;
+	u32 count;
+	u16 part_id = 0;
+	struct udevice *dev;
+	struct ffa_partition_desc *descs = NULL;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Query partitions count using  invalid arguments */
+	ret = ffa_partition_info_get(dev, NULL, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, NULL);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID  string */
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid_str, &count, &descs);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, &descs);
+	ut_asserteq(0, count);
+
+	/* Query partitions data using a valid UUID */
+	count = 0;
+	ut_assertok(ffa_partition_info_get(dev, valid_svc_uuid, &count, &descs));
+	/* Make sure partitions are detected */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+	ut_assertnonnull(descs);
+
+	/* Send data to an invalid partition */
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Send data to a valid partition */
+	part_id = uc_priv->partitions.descs[0].info.id;
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v12 08/10] arm_ffa: introduce armffa command Sandbox test
  2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
                                                                                                               ` (6 preceding siblings ...)
  2023-05-12 12:10                                                                                             ` [PATCH v12 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-05-12 12:10                                                                                             ` Abdellatif El Khlifi
  2023-05-12 12:10                                                                                             ` [PATCH v12 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
                                                                                                               ` (2 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-12 12:10 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong

Add Sandbox test for the armffa command

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
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>

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

v12:

* address nits

v10:

* replace CMD_RET_SUCCESS with 0
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT

v9: align the test with FF-A discovery through DM

v4: drop use of helper APIs

v1: introduce armffa command sandbox test

 MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 1c81728b15..96141c9f59 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 055adc65a2..1d1dbb4fbc 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -23,6 +24,7 @@ obj-$(CONFIG_CMD_SEAMA) += seama.o
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_CMD_READ) += rw.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o
 endif
 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
 obj-$(CONFIG_CMD_WGET) += wget.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..9a44a397e8
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * 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 <string.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	/* armffa ping <ID> */
+	ut_assertok(run_commandf("armffa ping 0x%x", SANDBOX_SP1_ID));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return 0;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v12 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
                                                                                                               ` (7 preceding siblings ...)
  2023-05-12 12:10                                                                                             ` [PATCH v12 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2023-05-12 12:10                                                                                             ` Abdellatif El Khlifi
  2023-05-19 12:56                                                                                               ` Ilias Apalodimas
  2023-05-12 12:10                                                                                             ` [PATCH v12 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  2023-05-22  9:13                                                                                             ` [PATCH v12 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-12 12:10 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong, Gowtham Suresh Kumar

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

MM communication protocol supports FF-A 64-bit direct messaging.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>

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

v12:

* drop use of calloc when querying SPs
* address nits

v11:

* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* addressing nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* addressing nits

v9: align how FF-A is used with FF-A discovery through DM

v8:

* isolate the compilation choices between FF-A and OP-TEE
* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make mm_sp_svc_uuid static
* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
* improve use of unmap_sysmem() in ffa_mm_communicate()

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

 include/mm_communication.h        |  13 ++
 lib/efi_loader/Kconfig            |  14 +-
 lib/efi_loader/efi_variable_tee.c | 291 +++++++++++++++++++++++++++++-
 3 files changed, 312 insertions(+), 6 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..f17847583b 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,9 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *    Authors:
+ *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +16,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
@@ -248,4 +254,11 @@ struct smm_variable_var_check_property {
 	u16                       name[];
 };
 
+/* supported MM transports */
+enum mm_comms_select {
+	MM_COMMS_UNDEFINED,
+	MM_COMMS_FFA,
+	MM_COMMS_OPTEE
+};
+
 #endif /* _MM_COMMUNICATION_H_ */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c5835e6ef6..08a6b84101 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	depends on OPTEE || ARM_FFA_TRANSPORT
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..2effb705d7 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,9 +4,14 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  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 <efi.h>
 #include <efi_api.h>
 #include <efi_loader.h>
@@ -15,6 +20,36 @@
 #include <malloc.h>
 #include <mm_communication.h>
 
+#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)
+
+#include <arm_ffa.h>
+#include <cpu_func.h>
+#include <mapmem.h>
+
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_SIZE 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_OFFSET
+#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_OFFSET 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_ADDR 0
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+
+static const char *mm_sp_svc_uuid = MM_SP_UUID;
+
+static u16 mm_sp_id;
+
+#endif
+
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -24,6 +59,7 @@ struct mm_connection {
 	u32 session;
 };
 
+#if (IS_ENABLED(CONFIG_OPTEE))
 /**
  * get_connection() - Retrieve OP-TEE session for a specific UUID.
  *
@@ -60,6 +96,7 @@ static int get_connection(struct mm_connection *conn)
 out:
 	return rc;
 }
+#endif
 
 /**
  * optee_mm_communicate() - Pass a buffer to StandaloneMM running in OP-TEE
@@ -70,6 +107,7 @@ out:
  */
 static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 {
+#if (IS_ENABLED(CONFIG_OPTEE))
 	ulong buf_size;
 	efi_status_t ret;
 	struct efi_mm_communicate_header *mm_hdr;
@@ -142,19 +180,246 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 	}
 
 	return ret;
+#else
+	log_err("EFI: Please enable CONFIG_OPTEE for MM comms\n");
+	return EFI_UNSUPPORTED;
+#endif
 }
 
+#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)
+
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notify the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret = -1;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
+		return ret;
+	}
+
+	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
+
+	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
+	if (ret)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	if (sp_event_ret == MM_SUCCESS)
+		return 0;
+
+	/* Failure to notify the MM SP */
+
+	return -EACCES;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
+		return ret;
+	}
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, &descs);
+	if (ret) {
+		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
+		return ret;
+	}
+
+	/* MM SPs found , use the first one */
+
+	mm_sp_id = descs[0].info.id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	return 0;
+}
+#endif
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)
+	ulong tx_data_size;
+	int ffa_ret;
+	efi_status_t efi_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()) {
+		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+
+	switch (ffa_ret) {
+	case 0: {
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		efi_ret = EFI_SUCCESS;
+		break;
+	}
+	case -EINVAL:
+		efi_ret = EFI_DEVICE_ERROR;
+		break;
+	case -EPERM:
+		efi_ret = EFI_INVALID_PARAMETER;
+		break;
+	case -EACCES:
+		efi_ret = EFI_ACCESS_DENIED;
+		break;
+	case -EBUSY:
+		efi_ret = EFI_OUT_OF_RESOURCES;
+		break;
+	default:
+		efi_ret = EFI_ACCESS_DENIED;
+	}
+
+	unmap_sysmem(virt_shared_buf);
+	return efi_ret;
+#else
+	log_err("EFI: Please enable CONFIG_ARM_FFA_TRANSPORT for MM comms\n");
+	return EFI_UNSUPPORTED;
+#endif
+}
+
+/**
+ * select_mm_comms() - detect the available MM transport
+ *
+ * If FF-A is compiled in, make sure the FF-A bus is probed successfully
+ * which means FF-A communication with secure world works and ready
+ * to be used.
+ *
+ * If FF-A is not detected, check if OPTEE support is compiled in.
+ *
+ * Return:
+ *
+ * On success MM_COMMS_FFA or MM_COMMS_OPTEE. Otherwise, MM_COMMS_UNDEFINED
+ */
+static enum mm_comms_select select_mm_comms(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) {
+		ret = uclass_first_device_err(UCLASS_FFA, &dev);
+		if (ret)
+			log_err("EFI: Cannot find FF-A bus device, cannot select FF-A comms\n");
+		else
+			return MM_COMMS_FFA;
+	}
+
+	if (IS_ENABLED(CONFIG_OPTEE))
+		return MM_COMMS_OPTEE;
+
+	return MM_COMMS_UNDEFINED;
+}
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 {
 	efi_status_t ret;
+	enum mm_comms_select mm_comms;
 	struct efi_mm_communicate_header *mm_hdr;
 	struct smm_variable_communicate_header *var_hdr;
 
@@ -162,7 +427,18 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+	mm_comms = select_mm_comms();
+	switch (mm_comms) {
+	case MM_COMMS_UNDEFINED:
+		ret = EFI_UNSUPPORTED;
+		break;
+	case MM_COMMS_OPTEE:
+		ret = optee_mm_communicate(comm_buf, dsize);
+		break;
+	default:
+		ret = ffa_mm_communicate(comm_buf, dsize);
+	}
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -258,6 +534,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
 		goto out;
 	}
 	*size = var_payload->size;
+
+	#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)
+		if (*size > FFA_SHARED_MM_BUFFER_SIZE)
+			*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
+				MM_VARIABLE_COMMUNICATE_SIZE;
+	#endif
+
 	/*
 	 * There seems to be a bug in EDK2 miscalculating the boundaries and
 	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
@@ -697,7 +980,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v12 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
                                                                                                               ` (8 preceding siblings ...)
  2023-05-12 12:10                                                                                             ` [PATCH v12 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-05-12 12:10                                                                                             ` Abdellatif El Khlifi
  2023-05-22  9:13                                                                                             ` [PATCH v12 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-12 12:10 UTC (permalink / raw)
  To: abdellatif.elkhlifi
  Cc: Drew.Reed, achin.gupta, ilias.apalodimas, jens.wiklander, nd,
	robh, sjg, trini, u-boot, xueliang.zhong

turn on EFI MM communication

On corstone1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

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>

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

v9: update copyright string

v8:

* drop OP-TEE configs from Corstone-1000 defconfig

v7:

* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
  FFA_SHARED_MM_BUFFER_OFFSET
* update FFA_SHARED_MM_BUFFER_ADDR value

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

 configs/corstone1000_defconfig |  2 ++
 include/configs/corstone1000.h | 15 +++++++++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index 2d391048cd..0a48df9fbc 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -53,3 +53,5 @@ CONFIG_DM_SERIAL=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760=y
 CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
index 3347c11792..4ef1f05e40 100644
--- a/include/configs/corstone1000.h
+++ b/include/configs/corstone1000.h
@@ -1,9 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * (C) Copyright 2022 ARM Limited
  * (C) Copyright 2022 Linaro
  * Rui Miguel Silva <rui.silva@linaro.org>
- * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  *
  * Configuration for Corstone1000. Parts were derived from other ARM
  * configurations.
@@ -14,6 +16,15 @@
 
 #include <linux/sizes.h>
 
+#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
+
+/*
+ * shared buffer physical address used for communication between
+ * u-boot and the MM SP
+ */
+#define FFA_SHARED_MM_BUFFER_ADDR	0x02000000UL
+#define FFA_SHARED_MM_BUFFER_OFFSET	0
+
 #define V2M_BASE		0x80000000
 
 #define CFG_PL011_CLOCK	50000000
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-04-19  1:49                                                                                             ` Simon Glass
@ 2023-05-12 12:12                                                                                               ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-12 12:12 UTC (permalink / raw)
  To: Simon Glass; +Cc: ilias.apalodimas, nd, u-boot

On Tue, Apr 18, 2023 at 07:49:07PM -0600, Simon Glass wrote:

Hi Simon,

> 
> On Wed, 12 Apr 2023 at 03:43, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > Add MM communication support using FF-A transport
> >
> > This feature allows accessing MM partitions services through
> > EFI MM communication protocol. MM partitions such as StandAlonneMM
> > or smm-gateway secure partitions which reside in secure world.
> >
> > An MM shared buffer and a door bell event are used to exchange
> > the data.
> >
> > The data is used by EFI services such as GetVariable()/SetVariable()
> > and copied from the communication buffer to the MM shared buffer.
> >
> > The secure partition is notified about availability of data in the
> > MM shared buffer by an FF-A message (door bell).
> >
> > On such event, MM SP can read the data and updates the MM shared
> > buffer with the response data.
> >
> > The response data is copied back to the communication buffer and
> > consumed by the EFI subsystem.
> >
> > MM communication protocol supports FF-A 64-bit direct messaging.
> >
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>
> >
> > ---
> > Changelog:
> > ===============
> >
> > v11:
> >
> > * rename select_ffa_mm_comms() to select_mm_comms()
> > * improve the logic of MM transport selection in mm_communicate()
> > * addressing nits
> >
> > v10:
> >
> > * use the FF-A driver Uclass operations
> > * use uclass_first_device()
> > * addressing nits
> >
> > v9: align how FF-A is used with FF-A discovery through DM
> >
> > v8:
> >
> > * isolate the compilation choices between FF-A and OP-TEE
> > * update partition_info_get() second argument to be an SP count
> > * pass NULL device pointer to the FF-A bus discovery and operations
> >
> > v7:
> >
> > * set the MM door bell event to use 64-bit direct messaging
> > * issue a compile time error when one of these macros are not found :
> >   FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
> > * make mm_sp_svc_uuid static
> > * replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
> > * improve use of unmap_sysmem() in ffa_mm_communicate()
> >
> > v6:
> >
> > * add FF-A runtime discovery at MM communication level
> > * drop EFI runtime support for FF-A MM communication
> > * revert the changes in include/mm_communication.h for
> >   efi_mm_communicate_header and smm_variable_access structures
> >
> > v4:
> >
> > * use the new FF-A driver interfaces
> > * discover MM partitions at runtime
> > * copy FF-A driver private data to EFI runtime section at
> >   ExitBootServices()
> > * drop use of FFA_ERR_STAT_SUCCESS error code
> > * replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
> >   in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
> > * revert the error log in mm_communicate() in case of failure
> > * remove packed attribute from efi_mm_communicate_header and
> >   smm_variable_communicate_header
> >
> > v2:
> >
> > * set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings
> >
> > v1:
> >
> > * introduce FF-A MM communication
> >
> >  include/mm_communication.h        |  13 ++
> >  lib/efi_loader/Kconfig            |  14 +-
> >  lib/efi_loader/efi_variable_tee.c | 312 +++++++++++++++++++++++++++++-
> >  3 files changed, 333 insertions(+), 6 deletions(-)
> >
> > diff --git a/include/mm_communication.h b/include/mm_communication.h
> > index e65fbde60d..f17847583b 100644
> > --- a/include/mm_communication.h
> > +++ b/include/mm_communication.h
> > @@ -6,6 +6,9 @@
> >   *  Copyright (c) 2017, Intel Corporation. All rights reserved.
> >   *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
> >   *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
> > + *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> > + *    Authors:
> > + *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >
> >  #ifndef _MM_COMMUNICATION_H_
> > @@ -13,6 +16,9 @@
> >
> >  #include <part_efi.h>
> >
> > +/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
> > +#define MM_SP_UUID     "33d532ed-e699-0942-c09c-a798d9cd722d"
> > +
> >  /*
> >   * Interface to the pseudo Trusted Application (TA), which provides a
> >   * communication channel with the Standalone MM (Management Mode)
> > @@ -248,4 +254,11 @@ struct smm_variable_var_check_property {
> >         u16                       name[];
> >  };
> >
> > +/* supported MM transports */
> > +enum mm_comms_select {
> > +       MM_COMMS_UNDEFINED,
> > +       MM_COMMS_FFA,
> > +       MM_COMMS_OPTEE
> > +};
> > +
> >  #endif /* _MM_COMMUNICATION_H_ */
> > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > index c5835e6ef6..08a6b84101 100644
> > --- a/lib/efi_loader/Kconfig
> > +++ b/lib/efi_loader/Kconfig
> > @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
> >           stored as file /ubootefi.var on the EFI system partition.
> >
> >  config EFI_MM_COMM_TEE
> > -       bool "UEFI variables storage service via OP-TEE"
> > -       depends on OPTEE
> > +       bool "UEFI variables storage service via the trusted world"
> > +       depends on OPTEE || ARM_FFA_TRANSPORT
> >         help
> > +         Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
> > +         When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> > +         When using the u-boot FF-A  driver any MM SP is supported.
> > +
> >           If OP-TEE is present and running StandAloneMM, dispatch all UEFI
> >           variable related operations to that. The application will verify,
> >           authenticate and store the variables on an RPMB.
> >
> > +         When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> > +         operations to the MM SP running in the secure world.
> > +         A door bell mechanism is used to notify the SP when there is data in the shared
> > +         MM buffer. The data is copied by u-boot to the shared buffer before issuing
> > +         the door bell event.
> > +
> >  config EFI_VARIABLE_NO_STORE
> >         bool "Don't persist non-volatile UEFI variables"
> >         help
> > diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> > index dfef18435d..a6ec126db5 100644
> > --- a/lib/efi_loader/efi_variable_tee.c
> > +++ b/lib/efi_loader/efi_variable_tee.c
> > @@ -4,9 +4,14 @@
> >   *
> >   *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
> >   *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
> > + *  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 <efi.h>
> >  #include <efi_api.h>
> >  #include <efi_loader.h>
> > @@ -15,6 +20,36 @@
> >  #include <malloc.h>
> >  #include <mm_communication.h>
> >
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> > +
> > +#include <arm_ffa.h>
> > +#include <cpu_func.h>
> > +#include <mapmem.h>
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> > +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_SIZE 0
> > +#endif
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_OFFSET
> > +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_OFFSET 0
> > +#endif
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> > +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_ADDR 0
> > +#endif
> > +
> > +/* MM return codes */
> > +#define MM_SUCCESS (0)
> > +
> > +static const char *mm_sp_svc_uuid = MM_SP_UUID;
> > +
> > +static u16 mm_sp_id;
> > +
> > +#endif
> > +
> >  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
> >  static efi_uintn_t max_buffer_size;    /* comm + var + func + data */
> >  static efi_uintn_t max_payload_size;   /* func + data */
> > @@ -24,6 +59,7 @@ struct mm_connection {
> >         u32 session;
> >  };
> >
> > +#if (IS_ENABLED(CONFIG_OPTEE))
> >  /**
> >   * get_connection() - Retrieve OP-TEE session for a specific UUID.
> >   *
> > @@ -60,6 +96,7 @@ static int get_connection(struct mm_connection *conn)
> >  out:
> >         return rc;
> >  }
> > +#endif
> >
> >  /**
> >   * optee_mm_communicate() - Pass a buffer to StandaloneMM running in OP-TEE
> > @@ -70,6 +107,7 @@ out:
> >   */
> >  static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
> >  {
> > +#if (IS_ENABLED(CONFIG_OPTEE))
> >         ulong buf_size;
> >         efi_status_t ret;
> >         struct efi_mm_communicate_header *mm_hdr;
> > @@ -142,19 +180,269 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
> >         }
> >
> >         return ret;
> > +#else
> > +       log_err("EFI: Please enable CONFIG_OPTEE for MM comms\n");
> > +       return EFI_UNSUPPORTED;
> > +#endif
> > +}
> > +
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> 
> drop extra brackets
> 
> > +
> > +/**
> > + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> > + *
> > + * Notify the MM partition in the trusted world that
> > + * data is available in the shared buffer.
> > + * This is a blocking call during which trusted world has exclusive access
> > + * to the MM shared buffer.
> > + *
> > + * Return:
> > + *
> > + * 0 on success
> > + */
> > +static int ffa_notify_mm_sp(void)
> > +{
> > +       struct ffa_send_direct_data msg = {0};
> > +       int ret;
> > +       int sp_event_ret = -1;
> > +       struct udevice *dev;
> > +
> > +       ret = uclass_first_device_err(UCLASS_FFA, &dev);
> > +       if (ret) {
> > +               log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
> > +               return -ENODEV;
> 
> return ret
> 
> > +       }
> > +
> > +       msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
> > +
> > +       ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
> > +       if (ret)
> > +               return ret;
> > +
> > +       sp_event_ret = msg.data0; /* x3 */
> > +
> > +       if (sp_event_ret == MM_SUCCESS)
> > +               return 0;
> > +
> > +       /* Failure to notify the MM SP */
> > +
> > +       return -EACCES;
> > +}
> > +
> > +/**
> > + * ffa_discover_mm_sp_id() - Query the MM partition ID
> > + *
> > + * Use the FF-A driver to get the MM partition ID.
> > + * If multiple partitions are found, use the first one.
> > + * This is a boot time function.
> > + *
> > + * Return:
> > + *
> > + * 0 on success
> > + */
> > +static int ffa_discover_mm_sp_id(void)
> > +{
> > +       u32 count = 0;
> > +       int ret;
> > +       struct ffa_partition_info *parts_info;
> > +       struct udevice *dev;
> > +
> > +       ret = uclass_first_device_err(UCLASS_FFA, &dev);
> > +       if (ret) {
> > +               log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
> > +               return -ENODEV;
> 
> return ret
> 
> Please check that you don't change error returns unless you really
> want to, as it makes it hard to debug failures.
> 
> > +       }
> > +
> > +       /* Get from the driver the count of the SPs matching the UUID */
> > +       ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, NULL);
> > +       if (ret) {
> > +               log_err("EFI: Failure in querying SPs count (%d), MM SP discovery failure\n", ret);
> > +               return ret;
> > +       }
> > +
> > +       if (!count) {
> > +               log_info("EFI: No MM partition found\n");
> > +               return ret;
> > +       }
> > +
> > +       /* Pre-allocate a buffer to be filled by the driver with ffa_partition_info structs */
> > +
> > +       log_info("EFI: Pre-allocating %d partition(s) info structures\n", count);
> > +
> > +       parts_info = calloc(count, sizeof(*parts_info));
> 
> Use a local var and drop the calloc()
> 
> > +       if (!parts_info)
> > +               return -ENOMEM;
> > +
> > +       /* Ask the driver to fill the buffer with the SPs info */
> > +       ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, parts_info);
> > +       if (ret) {
> > +               log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
> > +               free(parts_info);
> > +               return ret;
> > +       }
> > +
> > +       /* MM SPs found , use the first one */
> > +
> > +       mm_sp_id = parts_info[0].id;
> > +
> > +       log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
> > +
> > +       free(parts_info);
> > +
> > +       return 0;
> > +}
> > +#endif
> > +
> > +/**
> > + * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
> > + * @comm_buf:          locally allocated communication buffer used for rx/tx
> > + * @dsize:                             communication buffer size
> > + *
> > + * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
> > + * that there is data to read from the shared buffer.
> > + * Communication with the MM SP is performed using FF-A transport.
> > + * On the event, MM SP can read the data from the buffer and
> > + * update the MM shared buffer with response data.
> > + * The response data is copied back to the communication buffer.
> > + *
> > + * Return:
> > + *
> > + * EFI status code
> > + */
> > +static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
> > +{
> > +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> 
> Please use if() if you can?

Thanks for pointing out this. I'm trying my best to reduce the #ifdefs as much as possible.
For this one, what goes under the #ifdef is specific to FF-A. It doesn't make sense to compile
the FF-A logic and functions when we don't turn on the FF-A config.
I agreed with Ilias to keep ffa_mm_communicate() as a stub in case FF-A is off, and to show a message
at the preprocessor level.

> 
> > +       ulong tx_data_size;
> > +       int ffa_ret;
> > +       efi_status_t efi_ret;
> > +       struct efi_mm_communicate_header *mm_hdr;
> > +       void *virt_shared_buf;
> > +
> > +       if (!comm_buf)
> > +               return EFI_INVALID_PARAMETER;
> > +
> > +       /* Discover MM partition ID at boot time */
> > +       if (!mm_sp_id && ffa_discover_mm_sp_id()) {
> > +               log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
> > +               return EFI_UNSUPPORTED;
> > +       }
> > +
> > +       mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> > +       tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
> > +
> > +       if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
> > +               return EFI_INVALID_PARAMETER;
> > +
> > +       /* Copy the data to the shared buffer */
> > +
> > +       virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
> > +       memcpy(virt_shared_buf, comm_buf, tx_data_size);
> > +
> > +       /*
> > +        * The secure world might have cache disabled for
> > +        * the device region used for shared buffer (which is the case for Optee).
> > +        * In this case, the secure world reads the data from DRAM.
> > +        * Let's flush the cache so the DRAM is updated with the latest data.
> > +        */
> > +#ifdef CONFIG_ARM64
> > +       invalidate_dcache_all();
> > +#endif
> > +
> > +       /* Announce there is data in the shared buffer */
> > +
> > +       ffa_ret = ffa_notify_mm_sp();
> > +
> > +       switch (ffa_ret) {
> > +       case 0: {
> > +               ulong rx_data_size;
> > +               /* Copy the MM SP response from the shared buffer to the communication buffer */
> > +               rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> > +                       sizeof(efi_guid_t) +
> > +                       sizeof(size_t);
> > +
> > +               if (rx_data_size > comm_buf_size) {
> > +                       efi_ret = EFI_OUT_OF_RESOURCES;
> > +                       break;
> > +               }
> > +
> > +               memcpy(comm_buf, virt_shared_buf, rx_data_size);
> > +               efi_ret = EFI_SUCCESS;
> > +               break;
> > +       }
> > +       case -EINVAL:
> > +               efi_ret = EFI_DEVICE_ERROR;
> > +               break;
> > +       case -EPERM:
> > +               efi_ret = EFI_INVALID_PARAMETER;
> > +               break;
> > +       case -EACCES:
> > +               efi_ret = EFI_ACCESS_DENIED;
> > +               break;
> > +       case -EBUSY:
> > +               efi_ret = EFI_OUT_OF_RESOURCES;
> > +               break;
> > +       default:
> > +               efi_ret = EFI_ACCESS_DENIED;
> > +       }
> > +
> > +       unmap_sysmem(virt_shared_buf);
> > +       return efi_ret;
> > +#else
> > +       log_err("EFI: Please enable CONFIG_ARM_FFA_TRANSPORT for MM comms\n");
> > +       return EFI_UNSUPPORTED;
> > +#endif
> > +}
> > +
> > +/**
> > + * select_mm_comms() - detect the available MM transport
> > + *
> > + * If FF-A is compiled in, make sure the FF-A bus is probed successfully
> > + * which means FF-A communication with secure world works and ready
> > + * to be used.
> > + *
> > + * If FF-A is not detected, check if OPTEE support is compiled in.
> > + *
> > + * Return:
> > + *
> > + * On success MM_COMMS_FFA or MM_COMMS_OPTEE. Otherwise, MM_COMMS_UNDEFINED
> > + */
> > +static enum mm_comms_select select_mm_comms(void)
> > +{
> > +       struct udevice *dev;
> > +       int ret;
> > +
> > +       if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) {
> > +               ret = uclass_first_device_err(UCLASS_FFA, &dev);
> > +               if (ret)
> > +                       log_err("EFI: Cannot find FF-A bus device, cannot select FF-A comms\n");
> > +               else
> > +                       return MM_COMMS_FFA;
> > +       }
> > +
> > +       if (IS_ENABLED(CONFIG_OPTEE))
> > +               return MM_COMMS_OPTEE;
> > +
> > +       return MM_COMMS_UNDEFINED;
> >  }
> >
> >  /**
> > - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
> > + * mm_communicate() - Adjust the communication buffer to the MM SP and send
> >   * it to OP-TEE
> >   *
> > - * @comm_buf:          locally allocted communcation buffer
> > + * @comm_buf:          locally allocated communication buffer
> >   * @dsize:             buffer size
> > + *
> > + * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
> > + * The comm_buf format is the same for both partitions.
> > + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> > + * When using the u-boot FF-A  driver, any MM SP is supported.
> > + *
> >   * Return:             status code
> >   */
> >  static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> >  {
> >         efi_status_t ret;
> > +       enum mm_comms_select mm_comms;
> >         struct efi_mm_communicate_header *mm_hdr;
> >         struct smm_variable_communicate_header *var_hdr;
> >
> > @@ -162,7 +450,16 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> >         mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> >         var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
> >
> > -       ret = optee_mm_communicate(comm_buf, dsize);
> > +       mm_comms = select_mm_comms();
> > +       if (mm_comms == MM_COMMS_UNDEFINED) {
> > +               ret = EFI_UNSUPPORTED;
> > +       } else {
> > +               if (mm_comms == MM_COMMS_OPTEE)
> > +                       ret = optee_mm_communicate(comm_buf, dsize);
> > +               else
> > +                       ret = ffa_mm_communicate(comm_buf, dsize);
> > +       }
> > +
> >         if (ret != EFI_SUCCESS) {
> >                 log_err("%s failed!\n", __func__);
> >                 return ret;
> > @@ -258,6 +555,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
> >                 goto out;
> >         }
> >         *size = var_payload->size;
> > +
> > +       #if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
> 
> Can this use if () ?

FFA_SHARED_MM_BUFFER_SIZE is a platform-specific value related to the MM layer (firmware).
Platforms that don't use FF-A won't define FFA_SHARED_MM_BUFFER_SIZE, leading to a compilation error.
So, we need to use an #ifdef in this case.

Cheers,
Abdellatif

> 
> > +               if (*size > FFA_SHARED_MM_BUFFER_SIZE)
> > +                       *size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE  -
> > +                               MM_VARIABLE_COMMUNICATE_SIZE;
> > +       #endif
> > +
> >         /*
> >          * There seems to be a bug in EDK2 miscalculating the boundaries and
> >          * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> > @@ -697,7 +1001,7 @@ void efi_variables_boot_exit_notify(void)
> >                 ret = EFI_NOT_FOUND;
> >
> >         if (ret != EFI_SUCCESS)
> > -               log_err("Unable to notify StMM for ExitBootServices\n");
> > +               log_err("Unable to notify the MM partition for ExitBootServices\n");
> >         free(comm_buf);
> >
> >         /*
> > --
> > 2.25.1
> >
> 
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v11 05/10] arm_ffa: introduce armffa command
  2023-04-19  1:49                                                                                             ` Simon Glass
@ 2023-05-12 12:14                                                                                               ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-12 12:14 UTC (permalink / raw)
  To: Simon Glass; +Cc: nd, u-boot

Hi Simon,

> 
> On Wed, 12 Apr 2023 at 03:43, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > Provide armffa command showcasing the use of the U-Boot FF-A support
> >
> > armffa is a command showcasing how to invoke FF-A operations.
> > This provides a guidance to the client developers on how to
> > call the FF-A bus interfaces. The command also allows to gather secure
> > partitions information and ping these  partitions. The command is also
> > helpful in testing the communication with secure partitions.
> >
> > For more details please refer to the command documentation [1].
> >
> > [1]: doc/usage/cmd/armffa.rst
> >
> > 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>
> > Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
> >
> > ---
> > Changelog:
> > ===============
> >
> > v11:
> >
> > * use U_BOOT_CMD_WITH_SUBCMDS
> > * address nits
> >
> > v10:
> >
> > * use the FF-A driver Uclass operations
> > * use uclass_first_device()
> > * address nits
> >
> > v9:
> >
> > * remove manual FF-A discovery and use DM
> > * use DM class APIs to probe and interact with the FF-A bus
> > * add doc/usage/cmd/armffa.rst
> >
> > v8:
> >
> > * update partition_info_get() second argument to be an SP count
> > * pass NULL device pointer to the FF-A bus discovery and operations
> >
> > v7:
> >
> > * adapt do_ffa_dev_list() following the recent update on
> >   uclass_first_device/uclass_next_device functions (they return void now)
> > * set armffa command to use 64-bit direct messaging
> >
> > v4:
> >
> > * remove pattern data in do_ffa_msg_send_direct_req
> >
> > v3:
> >
> > * use the new driver interfaces (partition_info_get, sync_send_receive)
> >   in armffa command
> >
> > v2:
> >
> > * replace use of ffa_helper_init_device function by
> >  ffa_helper_bus_discover
> >
> > v1:
> >
> > * introduce armffa command
> >
> >  MAINTAINERS                      |   2 +
> >  cmd/Kconfig                      |  10 ++
> >  cmd/Makefile                     |   2 +
> >  cmd/armffa.c                     | 212 +++++++++++++++++++++++++++++++
> >  doc/arch/arm64.ffa.rst           |   7 +
> >  doc/usage/cmd/armffa.rst         | 105 +++++++++++++++
> >  doc/usage/index.rst              |   1 +
> >  drivers/firmware/arm-ffa/Kconfig |   1 +
> >  8 files changed, 340 insertions(+)
> >  create mode 100644 cmd/armffa.c
> >  create mode 100644 doc/usage/cmd/armffa.rst
> >
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
> with nits below
> 
> For your docs, please use a proper rST link for
> doc/usage/cmd/armffa.rst so people can click on it and view the
> command docs.
> 
> Also:
> 
> armffa is an implementation-defined command
> 
> (add hyphen)
> 
> although I'm not sure how an implementation can define the command?
> 
> The example output in your 'example' docs is very, very verbose.
> Shouldn't it just report problems?

Thanks, addressed in v12.

Cheers,
Abdellatif

> 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 76f0f276ce..c64804ca2d 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -269,7 +269,9 @@ F:  configs/cortina_presidio-asic-pnand_defconfig
> >  ARM FF-A
> >  M:     Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >  S:     Maintained
> > +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
> > diff --git a/cmd/Kconfig b/cmd/Kconfig
> > index 8c9b430f99..4cb0b2c167 100644
> > --- a/cmd/Kconfig
> > +++ b/cmd/Kconfig
> > @@ -934,6 +934,16 @@ endmenu
> >
> >  menu "Device access commands"
> >
> > +config CMD_ARMFFA
> > +       bool "Arm FF-A test command"
> > +       depends on ARM_FFA_TRANSPORT
> > +       help
> > +         Provides a test command for the FF-A support
> > +         supported options:
> > +               - Listing the partition(s) info
> > +               - Sending a data pattern to the specified partition
> > +               - Displaying the arm_ffa device info
> > +
> >  config CMD_ARMFLASH
> >         #depends on FLASH_CFI_DRIVER
> >         bool "armflash"
> > diff --git a/cmd/Makefile b/cmd/Makefile
> > index e032091621..9130b9078d 100644
> > --- a/cmd/Makefile
> > +++ b/cmd/Makefile
> > @@ -12,6 +12,8 @@ obj-y += panic.o
> >  obj-y += version.o
> >
> >  # command
> > +
> 
> Please drop blank line
> 
> > +obj-$(CONFIG_CMD_ARMFFA) += armffa.o
> >  obj-$(CONFIG_CMD_ACPI) += acpi.o
> >  obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
> >  obj-$(CONFIG_CMD_AES) += aes.o
> > diff --git a/cmd/armffa.c b/cmd/armffa.c
> > new file mode 100644
> > index 0000000000..ab88412c7d
> > --- /dev/null
> > +++ b/cmd/armffa.c
> > @@ -0,0 +1,212 @@
> > +// 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 <command.h>
> > +#include <dm.h>
> > +#include <mapmem.h>
> > +#include <stdlib.h>
> > +#include <asm/io.h>
> > +
> > +/**
> > + * ffa_get_dev() - Return the FF-A device
> > + * @devp:      pointer to the FF-A device
> > + *
> > + * Search for the FF-A device.
> > + *
> > + * Return:
> > + * 0 on success. Otherwise, failure
> > + */
> > +int ffa_get_dev(struct udevice **devp)
> > +{
> > +       int ret;
> > +
> > +       ret = uclass_first_device_err(UCLASS_FFA, devp);
> > +       if (ret) {
> > +               log_err("Cannot find FF-A bus device\n");
> > +               return -ENODEV;
> 
> return ret
> 
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +/**
> > + * do_ffa_getpart() - implementation of the getpart subcommand
> > + * @cmdtp:             Command Table
> > + * @flag:              flags
> > + * @argc:              number of arguments
> > + * @argv:              arguments
> > + *
> > + * Query the secure partition information which the UUID is provided
> > + * as an argument. The function uses the arm_ffa driver
> > + * partition_info_get operation which implements FFA_PARTITION_INFO_GET
> > + * ABI to retrieve the data. The input UUID string is expected to be in big
> > + * endian format.
> > + *
> > + * Return:
> > + *
> > + * CMD_RET_SUCCESS: on success, otherwise failure
> > + */
> > +static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
> > +                         char *const argv[])
> > +{
> > +       u32 count = 0;
> > +       int ret;
> > +       struct ffa_partition_info *parts_info;
> > +       u32 i;
> > +       struct udevice *dev;
> > +
> > +       ret = ffa_get_dev(&dev);
> > +       if (ret)
> > +               return CMD_RET_FAILURE;
> > +
> > +       /* Mode 1: getting the number of secure partitions */
> > +       ret = ffa_partition_info_get(dev, argv[1], &count, NULL);
> > +       if (ret) {
> > +               log_err("Failure in querying partitions count (error code: %d)\n", ret);
> > +               return CMD_RET_FAILURE;
> > +       }
> > +
> > +       if (!count) {
> > +               log_info("No secure partition found\n");
> > +               return CMD_RET_FAILURE;
> > +       }
> > +
> > +       /*
> > +        * Pre-allocate a buffer to be filled by the driver
> > +        * with ffa_partition_info structs
> > +        */
> > +
> > +       log_info("Pre-allocating %d partition(s) info structures\n", count);
> > +
> > +       parts_info = calloc(count, sizeof(struct ffa_partition_info));
> 
> This should be a local variable:
> 
> struct ffa_partition_info parts_info
> 
> I mentioned this before and you said that the number of things is
> fixed at runtime, but I don't see that here. Also I see is a simple
> struct, so there should be no need to allocate it.
> 
> > +       if (!parts_info)
> > +               return CMD_RET_FAILURE;
> > +
> > +       /* Ask the driver to fill the buffer with the SPs info */
> > +
> > +       ret = ffa_partition_info_get(dev, argv[1], &count, parts_info);
> > +       if (ret) {
> > +               log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
> > +               free(parts_info);
> > +               return CMD_RET_FAILURE;
> > +       }
> > +
> > +       /* SPs found , show the partition information */
> > +       for (i = 0; i < count ; i++) {
> > +               log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
> > +                        parts_info[i].id,
> > +                        parts_info[i].exec_ctxt,
> > +                        parts_info[i].properties);
> > +       }
> > +
> > +       free(parts_info);
> > +
> > +       return CMD_RET_SUCCESS;
> > +}
> > +
> [..]
> 
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v12 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-05-12 12:10                                                                                             ` [PATCH v12 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-05-19 12:56                                                                                               ` Ilias Apalodimas
  2023-05-19 13:36                                                                                                 ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-05-19 12:56 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, jens.wiklander, nd, robh, sjg, trini,
	u-boot, xueliang.zhong, Gowtham Suresh Kumar

Hi Abdellatif

I still have some concerns on this

In the past [0] I asking why this needs to be a Kconfig option.  Since FF-A
is a mechanism we can use to discover SPs, in theory we dont need the
ifdefery.  We might need something if the code difference grows too much
but I think we are fine for now. 

On top of that I am nissing how was this tested?  did you test the current
SMC to optee and the stmm for the RPMB backend?

> +++ b/include/mm_communication.h
> @@ -6,6 +6,9 @@
>   *  Copyright (c) 2017, Intel Corporation. All rights reserved.
>   *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
>   *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
> + *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *    Authors:
> + *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #ifndef _MM_COMMUNICATION_H_
> @@ -13,6 +16,9 @@
>  
>  #include <part_efi.h>
>  
> +/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
> +#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
> +
>  /*
>   * Interface to the pseudo Trusted Application (TA), which provides a
>   * communication channel with the Standalone MM (Management Mode)
> @@ -248,4 +254,11 @@ struct smm_variable_var_check_property {
>  	u16                       name[];
>  };
>  
> +/* supported MM transports */
> +enum mm_comms_select {
> +	MM_COMMS_UNDEFINED,
> +	MM_COMMS_FFA,
> +	MM_COMMS_OPTEE
> +};
> +
>  #endif /* _MM_COMMUNICATION_H_ */
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index c5835e6ef6..08a6b84101 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
>  	  stored as file /ubootefi.var on the EFI system partition.
>  
>  config EFI_MM_COMM_TEE
> -	bool "UEFI variables storage service via OP-TEE"
> -	depends on OPTEE
> +	bool "UEFI variables storage service via the trusted world"
> +	depends on OPTEE || ARM_FFA_TRANSPORT
>  	help
> +	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
> +	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> +	  When using the u-boot FF-A  driver any MM SP is supported.
> +
>  	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
>  	  variable related operations to that. The application will verify,
>  	  authenticate and store the variables on an RPMB.
>  
> +	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> +	  operations to the MM SP running in the secure world.
> +	  A door bell mechanism is used to notify the SP when there is data in the shared
> +	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
> +	  the door bell event.
> +
>  config EFI_VARIABLE_NO_STORE
>  	bool "Don't persist non-volatile UEFI variables"
>  	help
> diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> index dfef18435d..2effb705d7 100644
> --- a/lib/efi_loader/efi_variable_tee.c
> +++ b/lib/efi_loader/efi_variable_tee.c
> @@ -4,9 +4,14 @@
>   *
>   *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
>   *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
> + *  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 <efi.h>
>  #include <efi_api.h>
>  #include <efi_loader.h>
> @@ -15,6 +20,36 @@
>  #include <malloc.h>
>  #include <mm_communication.h>
>  
> +#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)
> +
> +#include <arm_ffa.h>
> +#include <cpu_func.h>
> +#include <mapmem.h>
> +
> +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_SIZE 0
> +#endif
> +
> +#ifndef FFA_SHARED_MM_BUFFER_OFFSET
> +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_OFFSET 0
> +#endif
> +
> +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
> +#define FFA_SHARED_MM_BUFFER_ADDR 0
> +#endif
> +
> +/* MM return codes */
> +#define MM_SUCCESS (0)
> +
> +static const char *mm_sp_svc_uuid = MM_SP_UUID;
> +
> +static u16 mm_sp_id;
> +
> +#endif
> +
>  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
>  static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
>  static efi_uintn_t max_payload_size;	/* func + data */
> @@ -24,6 +59,7 @@ struct mm_connection {
>  	u32 session;
>  };
>  
> +#if (IS_ENABLED(CONFIG_OPTEE))

>  /**
>   * get_connection() - Retrieve OP-TEE session for a specific UUID.
>   *

[...]

Isn't this problematic?  At the moment there's not > 8.4 hardware out
there.  As a result the SPMC *is* implemented in OP-TEE.  So how do we
expect FF-A to work?

[...]

[0] https://lore.kernel.org/u-boot/Y3NV991bKRgas1zZ@hera/

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v12 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-05-12 12:10                                                                                             ` [PATCH v12 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-05-19 12:56                                                                                               ` Ilias Apalodimas
  0 siblings, 0 replies; 478+ messages in thread
From: Ilias Apalodimas @ 2023-05-19 12:56 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Drew.Reed, achin.gupta, jens.wiklander, nd, robh, sjg, trini,
	u-boot, xueliang.zhong

On Fri, May 12, 2023 at 01:10:35PM +0100, Abdellatif El Khlifi wrote:
> add support for x0-x17 registers used by the SMC calls
> 
> In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
> Results are returned in x0-x17.
> 
> This work is inspired from the following kernel commit:
> 
> arm64: smccc: Add support for SMCCCv1.2 extended input/output registers
> 
> [1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
> 
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> 
> ---
> 
> Changelog:
> ===============
> 
> v9:
> 
> * update the copyright string
> 
> v7:
> 
> * improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS
> 
> v4:
> 
> * rename the commit title and improve description
>   new commit title: the current
> 
> v3:
> 
> * port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
>   commit title:
>       arm64: smccc: add Xn registers support used by SMC calls
> 
>  arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
>  arch/arm/lib/asm-offsets.c      | 16 +++++++++
>  include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
>  3 files changed, 117 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
> index dc92b28777..93f66d3366 100644
> --- a/arch/arm/cpu/armv8/smccc-call.S
> +++ b/arch/arm/cpu/armv8/smccc-call.S
> @@ -1,7 +1,11 @@
>  /* SPDX-License-Identifier: GPL-2.0 */
>  /*
>   * Copyright (c) 2015, Linaro Limited
> - */
> + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *
> + * Authors:
> + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +*/
>  #include <linux/linkage.h>
>  #include <linux/arm-smccc.h>
>  #include <generated/asm-offsets.h>
> @@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc)
>  ENTRY(__arm_smccc_hvc)
>  	SMCCC	hvc
>  ENDPROC(__arm_smccc_hvc)
> +
> +#ifdef CONFIG_ARM64
> +
> +	.macro SMCCC_1_2 instr
> +	/* Save `res` and free a GPR that won't be clobbered */
> +	stp     x1, x19, [sp, #-16]!
> +
> +	/* Ensure `args` won't be clobbered while loading regs in next step */
> +	mov	x19, x0
> +
> +	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
> +	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
> +	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
> +	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
> +	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
> +	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
> +	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
> +	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
> +	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
> +	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
> +
> +	\instr #0
> +
> +	/* Load the `res` from the stack */
> +	ldr	x19, [sp]
> +
> +	/* Store the registers x0 - x17 into the result structure */
> +	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
> +	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
> +	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
> +	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
> +	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
> +	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
> +	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
> +	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
> +	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
> +
> +	/* Restore original x19 */
> +	ldp     xzr, x19, [sp], #16
> +	ret
> +	.endm
> +
> +/*
> + * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
> + *			  struct arm_smccc_1_2_regs *res);
> + */
> +ENTRY(arm_smccc_1_2_smc)
> +	SMCCC_1_2 smc
> +ENDPROC(arm_smccc_1_2_smc)
> +
> +#endif
> diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
> index 6de0ce9152..181a8ac4c2 100644
> --- a/arch/arm/lib/asm-offsets.c
> +++ b/arch/arm/lib/asm-offsets.c
> @@ -9,6 +9,11 @@
>   * generate asm statements containing #defines,
>   * compile this file to assembler, and then extract the
>   * #defines from the assembly-language output.
> + *
> + * 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>
> @@ -90,6 +95,17 @@ int main(void)
>  	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
>  	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
>  	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
> +#ifdef CONFIG_ARM64
> +	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
> +	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
> +	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
> +	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
> +	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
> +	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
> +	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
> +	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
> +	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
> +#endif
>  #endif
>  
>  	return 0;
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index e1d09884a1..f44e9e8f93 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -1,6 +1,10 @@
>  /* SPDX-License-Identifier: GPL-2.0 */
>  /*
>   * Copyright (c) 2015, Linaro Limited
> + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *
> + * Authors:
> + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  #ifndef __LINUX_ARM_SMCCC_H
>  #define __LINUX_ARM_SMCCC_H
> @@ -70,6 +74,47 @@ struct arm_smccc_res {
>  	unsigned long a3;
>  };
>  
> +#ifdef CONFIG_ARM64
> +/**
> + * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
> + * @a0-a17 argument values from registers 0 to 17
> + */
> +struct arm_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;
> +};
> +
> +/**
> + * arm_smccc_1_2_smc() - make SMC calls
> + * @args: arguments passed via struct arm_smccc_1_2_regs
> + * @res: result values via struct arm_smccc_1_2_regs
> + *
> + * This function is used to make SMC calls following SMC Calling Convention
> + * v1.2 or above. The content of the supplied param are copied from the
> + * structure to registers prior to the SMC instruction. The return values
> + * are updated with the content from registers on return from the SMC
> + * instruction.
> + */
> +asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
> +				  struct arm_smccc_1_2_regs *res);
> +#endif
> +
>  /**
>   * struct arm_smccc_quirk - Contains quirk information
>   * @id: quirk identification
> -- 
> 2.25.1
> 

Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v12 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-05-19 12:56                                                                                               ` Ilias Apalodimas
@ 2023-05-19 13:36                                                                                                 ` Abdellatif El Khlifi
  2023-05-19 14:07                                                                                                   ` Ilias Apalodimas
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-19 13:36 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, nd

Hi Ilias,

> Hi Abdellatif
> 
> I still have some concerns on this
> 
> In the past [0] I asking why this needs to be a Kconfig option.  Since FF-A
> is a mechanism we can use to discover SPs, in theory we dont need the
> ifdefery.  We might need something if the code difference grows too much
> but I think we are fine for now.

Is my understanding correct you prefer that CONFIG_EFI_MM_COMM_TEE implies
CONFIG_ARM_FFA_TRANSPORT ? So, no ifdefs anymore in efi_variable_tee.c.

> 
> On top of that I am nissing how was this tested?  did you test the current
> SMC to optee and the stmm for the RPMB backend?

We use Corstone-1000 platform for testing FF-A.
U-Boot communicates with smm-gateway (leight version of stmm) using FF-A SMC ABIs.
In the secure world we use TF-A, Optee OS and Trusted Services providing smm-gateway SP.
In U-Boot we don't use the Optee driver because we use FF-A communication only.
I hope this clears all doubts.

Cheers
Abdellatif

> 
> > +++ b/include/mm_communication.h
> > @@ -6,6 +6,9 @@
> >   *  Copyright (c) 2017, Intel Corporation. All rights reserved.
> >   *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
> >   *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
> > + *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> > + *    Authors:
> > + *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   */
> >  
> >  #ifndef _MM_COMMUNICATION_H_
> > @@ -13,6 +16,9 @@
> >  
> >  #include <part_efi.h>
> >  
> > +/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
> > +#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
> > +
> >  /*
> >   * Interface to the pseudo Trusted Application (TA), which provides a
> >   * communication channel with the Standalone MM (Management Mode)
> > @@ -248,4 +254,11 @@ struct smm_variable_var_check_property {
> >  	u16                       name[];
> >  };
> >  
> > +/* supported MM transports */
> > +enum mm_comms_select {
> > +	MM_COMMS_UNDEFINED,
> > +	MM_COMMS_FFA,
> > +	MM_COMMS_OPTEE
> > +};
> > +
> >  #endif /* _MM_COMMUNICATION_H_ */
> > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > index c5835e6ef6..08a6b84101 100644
> > --- a/lib/efi_loader/Kconfig
> > +++ b/lib/efi_loader/Kconfig
> > @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
> >  	  stored as file /ubootefi.var on the EFI system partition.
> >  
> >  config EFI_MM_COMM_TEE
> > -	bool "UEFI variables storage service via OP-TEE"
> > -	depends on OPTEE
> > +	bool "UEFI variables storage service via the trusted world"
> > +	depends on OPTEE || ARM_FFA_TRANSPORT
> >  	help
> > +	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
> > +	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> > +	  When using the u-boot FF-A  driver any MM SP is supported.
> > +
> >  	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
> >  	  variable related operations to that. The application will verify,
> >  	  authenticate and store the variables on an RPMB.
> >  
> > +	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> > +	  operations to the MM SP running in the secure world.
> > +	  A door bell mechanism is used to notify the SP when there is data in the shared
> > +	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
> > +	  the door bell event.
> > +
> >  config EFI_VARIABLE_NO_STORE
> >  	bool "Don't persist non-volatile UEFI variables"
> >  	help
> > diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> > index dfef18435d..2effb705d7 100644
> > --- a/lib/efi_loader/efi_variable_tee.c
> > +++ b/lib/efi_loader/efi_variable_tee.c
> > @@ -4,9 +4,14 @@
> >   *
> >   *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
> >   *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
> > + *  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 <efi.h>
> >  #include <efi_api.h>
> >  #include <efi_loader.h>
> > @@ -15,6 +20,36 @@
> >  #include <malloc.h>
> >  #include <mm_communication.h>
> >  
> > +#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)
> > +
> > +#include <arm_ffa.h>
> > +#include <cpu_func.h>
> > +#include <mapmem.h>
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> > +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_SIZE 0
> > +#endif
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_OFFSET
> > +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_OFFSET 0
> > +#endif
> > +
> > +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> > +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
> > +#define FFA_SHARED_MM_BUFFER_ADDR 0
> > +#endif
> > +
> > +/* MM return codes */
> > +#define MM_SUCCESS (0)
> > +
> > +static const char *mm_sp_svc_uuid = MM_SP_UUID;
> > +
> > +static u16 mm_sp_id;
> > +
> > +#endif
> > +
> >  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
> >  static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
> >  static efi_uintn_t max_payload_size;	/* func + data */
> > @@ -24,6 +59,7 @@ struct mm_connection {
> >  	u32 session;
> >  };
> >  
> > +#if (IS_ENABLED(CONFIG_OPTEE))
> 
> >  /**
> >   * get_connection() - Retrieve OP-TEE session for a specific UUID.
> >   *
> 
> [...]
> 
> Isn't this problematic?  At the moment there's not > 8.4 hardware out
> there.  As a result the SPMC *is* implemented in OP-TEE.  So how do we
> expect FF-A to work?
> 
> [...]
> 
> [0] https://lore.kernel.org/u-boot/Y3NV991bKRgas1zZ@hera/
> 
> Thanks
> /Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v12 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-05-19 13:36                                                                                                 ` Abdellatif El Khlifi
@ 2023-05-19 14:07                                                                                                   ` Ilias Apalodimas
  0 siblings, 0 replies; 478+ messages in thread
From: Ilias Apalodimas @ 2023-05-19 14:07 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: u-boot, nd

On Fri, May 19, 2023 at 02:36:55PM +0100, Abdellatif El Khlifi wrote:
> Hi Ilias,
> 
> > Hi Abdellatif
> > 
> > I still have some concerns on this
> > 
> > In the past [0] I asking why this needs to be a Kconfig option.  Since FF-A
> > is a mechanism we can use to discover SPs, in theory we dont need the
> > ifdefery.  We might need something if the code difference grows too much
> > but I think we are fine for now.
> 
> Is my understanding correct you prefer that CONFIG_EFI_MM_COMM_TEE implies
> CONFIG_ARM_FFA_TRANSPORT ? So, no ifdefs anymore in efi_variable_tee.c.

I wonder what it takes to autodiscover that and get rid of all ifdefs
(OPTEE and FF-A).  In theory you could probe FF-A and if it's not there
switch to the smc calling no?

> 
> > 
> > On top of that I am nissing how was this tested?  did you test the current
> > SMC to optee and the stmm for the RPMB backend?
> 
> We use Corstone-1000 platform for testing FF-A.
> U-Boot communicates with smm-gateway (leight version of stmm) using FF-A SMC ABIs.
> In the secure world we use TF-A, Optee OS and Trusted Services providing smm-gateway SP.
> In U-Boot we don't use the Optee driver because we use FF-A communication only.
> I hope this clears all doubts.

Ok,  but you will still need to load op-tee from BL2.
My problem here is that this is a bit confusing from an architectural point
of view and people need to be aware of what config options to choose, but if
my understanding is correct we can automate that.

Thanks
/Ilias
> 
> Cheers
> Abdellatif
> 
> > 
> > > +++ b/include/mm_communication.h
> > > @@ -6,6 +6,9 @@
> > >   *  Copyright (c) 2017, Intel Corporation. All rights reserved.
> > >   *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
> > >   *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
> > > + *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> > > + *    Authors:
> > > + *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > >   */
> > >  
> > >  #ifndef _MM_COMMUNICATION_H_
> > > @@ -13,6 +16,9 @@
> > >  
> > >  #include <part_efi.h>
> > >  
> > > +/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
> > > +#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
> > > +
> > >  /*
> > >   * Interface to the pseudo Trusted Application (TA), which provides a
> > >   * communication channel with the Standalone MM (Management Mode)
> > > @@ -248,4 +254,11 @@ struct smm_variable_var_check_property {
> > >  	u16                       name[];
> > >  };
> > >  
> > > +/* supported MM transports */
> > > +enum mm_comms_select {
> > > +	MM_COMMS_UNDEFINED,
> > > +	MM_COMMS_FFA,
> > > +	MM_COMMS_OPTEE
> > > +};
> > > +
> > >  #endif /* _MM_COMMUNICATION_H_ */
> > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > index c5835e6ef6..08a6b84101 100644
> > > --- a/lib/efi_loader/Kconfig
> > > +++ b/lib/efi_loader/Kconfig
> > > @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE
> > >  	  stored as file /ubootefi.var on the EFI system partition.
> > >  
> > >  config EFI_MM_COMM_TEE
> > > -	bool "UEFI variables storage service via OP-TEE"
> > > -	depends on OPTEE
> > > +	bool "UEFI variables storage service via the trusted world"
> > > +	depends on OPTEE || ARM_FFA_TRANSPORT
> > >  	help
> > > +	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
> > > +	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> > > +	  When using the u-boot FF-A  driver any MM SP is supported.
> > > +
> > >  	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
> > >  	  variable related operations to that. The application will verify,
> > >  	  authenticate and store the variables on an RPMB.
> > >  
> > > +	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> > > +	  operations to the MM SP running in the secure world.
> > > +	  A door bell mechanism is used to notify the SP when there is data in the shared
> > > +	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
> > > +	  the door bell event.
> > > +
> > >  config EFI_VARIABLE_NO_STORE
> > >  	bool "Don't persist non-volatile UEFI variables"
> > >  	help
> > > diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> > > index dfef18435d..2effb705d7 100644
> > > --- a/lib/efi_loader/efi_variable_tee.c
> > > +++ b/lib/efi_loader/efi_variable_tee.c
> > > @@ -4,9 +4,14 @@
> > >   *
> > >   *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
> > >   *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
> > > + *  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 <efi.h>
> > >  #include <efi_api.h>
> > >  #include <efi_loader.h>
> > > @@ -15,6 +20,36 @@
> > >  #include <malloc.h>
> > >  #include <mm_communication.h>
> > >  
> > > +#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)
> > > +
> > > +#include <arm_ffa.h>
> > > +#include <cpu_func.h>
> > > +#include <mapmem.h>
> > > +
> > > +#ifndef FFA_SHARED_MM_BUFFER_SIZE
> > > +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
> > > +#define FFA_SHARED_MM_BUFFER_SIZE 0
> > > +#endif
> > > +
> > > +#ifndef FFA_SHARED_MM_BUFFER_OFFSET
> > > +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
> > > +#define FFA_SHARED_MM_BUFFER_OFFSET 0
> > > +#endif
> > > +
> > > +#ifndef FFA_SHARED_MM_BUFFER_ADDR
> > > +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
> > > +#define FFA_SHARED_MM_BUFFER_ADDR 0
> > > +#endif
> > > +
> > > +/* MM return codes */
> > > +#define MM_SUCCESS (0)
> > > +
> > > +static const char *mm_sp_svc_uuid = MM_SP_UUID;
> > > +
> > > +static u16 mm_sp_id;
> > > +
> > > +#endif
> > > +
> > >  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
> > >  static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
> > >  static efi_uintn_t max_payload_size;	/* func + data */
> > > @@ -24,6 +59,7 @@ struct mm_connection {
> > >  	u32 session;
> > >  };
> > >  
> > > +#if (IS_ENABLED(CONFIG_OPTEE))
> > 
> > >  /**
> > >   * get_connection() - Retrieve OP-TEE session for a specific UUID.
> > >   *
> > 
> > [...]
> > 
> > Isn't this problematic?  At the moment there's not > 8.4 hardware out
> > there.  As a result the SPMC *is* implemented in OP-TEE.  So how do we
> > expect FF-A to work?
> > 
> > [...]
> > 
> > [0] https://lore.kernel.org/u-boot/Y3NV991bKRgas1zZ@hera/
> > 
> > Thanks
> > /Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v12 00/10] introduce Arm FF-A support
  2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
                                                                                                               ` (9 preceding siblings ...)
  2023-05-12 12:10                                                                                             ` [PATCH v12 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
@ 2023-05-22  9:13                                                                                             ` Abdellatif El Khlifi
  2023-06-06 11:56                                                                                               ` Abdellatif El Khlifi
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-05-22  9:13 UTC (permalink / raw)
  To: abdellatif.elkhlifi, sjg; +Cc: nd, u-boot

Hi Simon,

> Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> 
> FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> communicate with each other. A partition could be a VM in the Normal or Secure world, an
> application in S-EL0, or a Trusted OS in S-EL1.
> 
> FF-A is a discoverable bus and similar to architecture features.
> FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> by the PSCI driver.
> 
>    => dm tree
> 
>     Class     Index  Probed  Driver                Name
>    -----------------------------------------------------------
>    ...
>     firmware      0  [ + ]   psci                      |-- psci
>     ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
>    ...
> 
> Clients are able to probe then use the FF-A bus by calling the DM class
> searching APIs (e.g: uclass_first_device).
> 
> This implementation of the specification provides support for Aarch64.
> 
> The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> 
>     - Discover the presence of secure partitions (SPs) of interest
>     - Access an SP's service through communication protocols
>       (e.g: EFI MM communication protocol)
> 
> The FF-A support provides the following features:
> 
>     - Being generic by design and can be used by any Arm 64-bit platform
>     - FF-A support can be compiled and used without EFI
>     - Support for SMCCCv1.2 x0-x17 registers
>     - Support for SMC32 calling convention
>     - Support for 32-bit and 64-bit FF-A direct messaging
>     - Support for FF-A MM communication (compatible with EFI boot time)
>     - Enabling FF-A and MM communication in Corstone1000 platform as a use case
>     - 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.
>     - Sandbox FF-A test cases.
>     - A new command called armffa is provided as an example of how to access the
>       FF-A bus
> 
> For more details about the FF-A support please refer to [B] and refer to [C] for
> how to use the armffa command.
> 
> Please find at [D] an example of the expected boot logs when enabling
> FF-A support for a platform. In this example the platform is
> Corstone1000. But it can be any Arm 64-bit platform.
> 
> Changelog of the major changes:
> ===========================
> 
> v12:
> 
> * remove the global variable (dscvry_info), use uc_priv instead
> * replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
>    (user drivers can override it)
> * improve FFA_PARTITION_INFO_GET implementation
>    (clients no longer need to calloc a buffer)
> * remove reparenting by making the sandbox emulator parent of the FF-A device in the DT
> * improve argument checks for the armffa command
> * address nits
> 
> v11: [11]
> 
> * move ffa_try_discovery() from the uclass to the Arm FF-A driver
> * rename ffa_try_discovery() to arm_ffa_discover()
> * add arm_ prefix to the Arm FF-A driver functions
> * use U_BOOT_CMD_WITH_SUBCMDS for armffa command
> * store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
> * set the emulator as parent of the sandbox FF-A device
> * rename select_ffa_mm_comms() to select_mm_comms()
> * improve the logic of MM transport selection in mm_communicate()
> * use ut_asserteq_mem() in uuid_str_to_le_bin test case
> * address nits
> 
> v10: [10]
> 
> * provide the FF-A driver operations through the Uclass (arm-ffa-uclass.c)
> * move the generic FF-A methods to the Uclass
> * keep Arm specific methods in the Arm driver (arm-ffa.c renamed from core.c)
> * split the FF-A sandbox support into an emulator (ffa-emul-uclass.c) and a driver (sandbox_ffa.c)
> * use the FF-A driver Uclass operations by clients (armffa command, tests, MM comms)
> * use uclass_first_device to search and probe the FF-A device (whether it is on Arm or on sandbox)
> * address nits
> 
> v9: [9]
> 
> * integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
> * align FF-A sandbox driver with FF-A discovery through DM
> * use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
> * add documentation for the armffa command: doc/usage/cmd/armffa.rst
> * introduce testcase for uuid_str_to_le_bin
> 
> v8: [8]
> 
> * pass the FF-A bus device to the bus operations
> * isolate the compilation choices between FF-A and OP-TEE
> * drop OP-TEE configs from Corstone-1000 defconfig
> * make ffa_get_partitions_info() second argument to be an SP count in both
>   modes
> 
> v7: [7]
> 
> * add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
> * set the MM door bell event to use 64-bit direct messaging
> * issue a compile time error when one of these macros are not found :
>   FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
> * make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
>   by using same APIs
> 
> v6: [6]
> 
> * remove clearing x0-x17 registers after SMC calls
> * drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
> * drop discovery from initcalls (discovery will be on demand by FF-A users)
> * add FF-A runtime discovery at MM communication level
> * update the documentation and move it to doc/arch/arm64.ffa.rst
> 
> v5: [5]
> 
> * move changelogs in each commit to the changes section
> 
> v4: [4]
> 
> * add FF-A support README (doc/README.ffa.drv)
> * improving error handling by mapping the FF-A errors to standard errors
>   and logs
> * replacing panics with an error log
> * align sandbox driver and tests with the new FF-A driver interfaces
>  and new way of error handling
> * use the new FF-A driver interfaces for MM communication
> * discover MM partitions at runtime
> * copy FF-A driver private data to EFI runtime section at
>   ExitBootServices()
> * moving the FF-A driver work to drivers/firmware/arm-ffa
> * improving features discovery in FFA_FEATURES
> * add remove/unbind functions to the FF-A core device
> * improve how the driver behaves when bus discovery is done more than
>   once
> * move clearing x0-x17 registers code into a new macro like done in
>    the linux kernel
> * enable EFI MM communication for the Corstone1000 platform
> 
> v3: [3]
> 
> * port x0-x17 registers support from linux kernel as defined by
>    SMCCCv1.2
> * align the interfaces of the u-boot FF-A driver with those in the linux
>    FF-A driver
> * remove the FF-A helper layer
> * make the u-boot FF-A driver independent from EFI
> * provide an optional config that enables copying the driver data to
>    EFI runtime section at ExitBootServices service
> * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
> * update armffa command with the new driver interfaces
> 
> v2  [2]:
> 
> * make FF-A bus discoverable using device_{bind, probe} APIs
> * remove device tree support
> 
> v1  [1]:
> 
> * introduce FF-A bus driver with device tree support
> * introduce armffa command
> * introduce FF-A Sandbox driver
> * add FF-A Sandbox test cases
> * introduce FF-A MM communication
> 
> Cheers,
> Abdellatif
> 
> List of previous patches:
> 
> [1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
> [2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
> [3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
> [4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
> [5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
> [6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
> [7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
> [8]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
> [9]: https://lore.kernel.org/all/20230310141016.137986-1-abdellatif.elkhlifi@arm.com/
> [10]: https://lore.kernel.org/all/20230328161157.219375-1-abdellatif.elkhlifi@arm.com/
> [11]: https://lore.kernel.org/all/20230412094245.44674-1-abdellatif.elkhlifi@arm.com/
> 
> More details:
> 
> [A]: https://developer.arm.com/documentation/den0077/latest/
> [B]: doc/arch/arm64.ffa.rst
> [C]: doc/usage/cmd/armffa.rst
> [D]: example of boot logs when enabling FF-A
> 
> ```
>    U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64
> 
>    DRAM:  2 GiB
>    Arm FF-A framework discovery
>    FF-A driver 1.0
>    FF-A framework 1.0
>    FF-A versions are compatible
>    ...
>    FF-A driver 1.0
>    FF-A framework 1.0
>    FF-A versions are compatible
>    EFI: MM partition ID 0x8003
>    ...
>    EFI stub: Booting Linux Kernel...
>    ...
>    Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
>    Machine model: ARM Corstone1000 FPGA MPS3 board
> ```
> 
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Simon Glass <sjg@chromium.org>

A gentle reminder about the v12 patchset.

Your feedback is more than welcome :)

Cheers

> Cc: Rob Herring <robh@kernel.org>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Cc: Jens Wiklander <jens.wiklander@linaro.org>
> Cc: Achin Gupta <achin.gupta@arm.com>
> Cc: Drew Reed <Drew.Reed@arm.com>
> Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>
> 
> Abdellatif El Khlifi (10):
>   arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
>   lib: uuid: introduce uuid_str_to_le_bin function
>   lib: uuid: introduce testcase for uuid_str_to_le_bin
>   arm_ffa: introduce Arm FF-A support
>   arm_ffa: introduce armffa command
>   arm_ffa: introduce sandbox FF-A support
>   arm_ffa: introduce sandbox test cases for UCLASS_FFA
>   arm_ffa: introduce armffa command Sandbox test
>   arm_ffa: efi: introduce FF-A MM communication
>   arm_ffa: efi: corstone1000: enable MM communication
> 
>  MAINTAINERS                                   |   18 +
>  arch/arm/cpu/armv8/smccc-call.S               |   57 +-
>  arch/arm/lib/asm-offsets.c                    |   16 +
>  arch/sandbox/dts/sandbox.dtsi                 |    9 +
>  arch/sandbox/dts/test.dts                     |    8 +
>  arch/sandbox/include/asm/sandbox_arm_ffa.h    |   72 ++
>  .../include/asm/sandbox_arm_ffa_priv.h        |  121 ++
>  cmd/Kconfig                                   |   10 +
>  cmd/Makefile                                  |    1 +
>  cmd/armffa.c                                  |  196 +++
>  configs/corstone1000_defconfig                |    2 +
>  configs/sandbox64_defconfig                   |    1 +
>  configs/sandbox_defconfig                     |    1 +
>  doc/arch/arm64.ffa.rst                        |  270 +++++
>  doc/arch/index.rst                            |    1 +
>  doc/arch/sandbox/sandbox.rst                  |    1 +
>  doc/usage/cmd/armffa.rst                      |   93 ++
>  doc/usage/index.rst                           |    1 +
>  drivers/Makefile                              |    1 +
>  drivers/firmware/Kconfig                      |    1 +
>  drivers/firmware/arm-ffa/Kconfig              |   42 +
>  drivers/firmware/arm-ffa/Makefile             |   16 +
>  drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
>  drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
>  drivers/firmware/arm-ffa/ffa-emul-uclass.c    |  720 +++++++++++
>  drivers/firmware/arm-ffa/sandbox_ffa.c        |  110 ++
>  include/arm_ffa.h                             |  213 ++++
>  include/arm_ffa_priv.h                        |  246 ++++
>  include/configs/corstone1000.h                |   15 +-
>  include/dm/uclass-id.h                        |    7 +
>  include/linux/arm-smccc.h                     |   45 +
>  include/mm_communication.h                    |   13 +
>  include/uuid.h                                |   15 +
>  lib/efi_loader/Kconfig                        |   14 +-
>  lib/efi_loader/efi_variable_tee.c             |  291 ++++-
>  lib/uuid.c                                    |   48 +
>  test/cmd/Makefile                             |    2 +
>  test/cmd/armffa.c                             |   33 +
>  test/dm/Makefile                              |    3 +-
>  test/dm/ffa.c                                 |  261 ++++
>  test/lib/Makefile                             |    1 +
>  test/lib/uuid.c                               |   41 +
>  42 files changed, 4175 insertions(+), 10 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 cmd/armffa.c
>  create mode 100644 doc/arch/arm64.ffa.rst
>  create mode 100644 doc/usage/cmd/armffa.rst
>  create mode 100644 drivers/firmware/arm-ffa/Kconfig
>  create mode 100644 drivers/firmware/arm-ffa/Makefile
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
>  create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
>  create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
>  create mode 100644 include/arm_ffa.h
>  create mode 100644 include/arm_ffa_priv.h
>  create mode 100644 test/cmd/armffa.c
>  create mode 100644 test/dm/ffa.c
>  create mode 100644 test/lib/uuid.c
> 
> -- 
> 2.25.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v12 00/10] introduce Arm FF-A support
  2023-05-22  9:13                                                                                             ` [PATCH v12 00/10] introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-06-06 11:56                                                                                               ` Abdellatif El Khlifi
  2023-06-06 13:48                                                                                                 ` Tom Rini
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-06-06 11:56 UTC (permalink / raw)
  To: sjg, trini; +Cc: sjg, trini, nd, u-boot, ilias.apalodimas

On Mon, May 22, 2023 at 10:13:20AM +0100, Abdellatif El Khlifi wrote:

Hi Simon, Tom,

> Hi Simon,
> 
> > Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> > 
> > FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> > communicate with each other. A partition could be a VM in the Normal or Secure world, an
> > application in S-EL0, or a Trusted OS in S-EL1.
> > 
> > FF-A is a discoverable bus and similar to architecture features.
> > FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> > by the PSCI driver.
> > 
> >    => dm tree
> > 
> >     Class     Index  Probed  Driver                Name
> >    -----------------------------------------------------------
> >    ...
> >     firmware      0  [ + ]   psci                      |-- psci
> >     ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
> >    ...
> > 
> > Clients are able to probe then use the FF-A bus by calling the DM class
> > searching APIs (e.g: uclass_first_device).
> > 
> > This implementation of the specification provides support for Aarch64.
> > 
> > The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> > 
> >     - Discover the presence of secure partitions (SPs) of interest
> >     - Access an SP's service through communication protocols
> >       (e.g: EFI MM communication protocol)
> > 
> > The FF-A support provides the following features:
> > 
> >     - Being generic by design and can be used by any Arm 64-bit platform
> >     - FF-A support can be compiled and used without EFI
> >     - Support for SMCCCv1.2 x0-x17 registers
> >     - Support for SMC32 calling convention
> >     - Support for 32-bit and 64-bit FF-A direct messaging
> >     - Support for FF-A MM communication (compatible with EFI boot time)
> >     - Enabling FF-A and MM communication in Corstone1000 platform as a use case
> >     - 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.
> >     - Sandbox FF-A test cases.
> >     - A new command called armffa is provided as an example of how to access the
> >       FF-A bus
> > 
> > For more details about the FF-A support please refer to [B] and refer to [C] for
> > how to use the armffa command.
> > 
> > Please find at [D] an example of the expected boot logs when enabling
> > FF-A support for a platform. In this example the platform is
> > Corstone1000. But it can be any Arm 64-bit platform.
> > 
> > Changelog of the major changes:
> > ===========================
> > 
> > v12:
> > 
> > * remove the global variable (dscvry_info), use uc_priv instead
> > * replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
> >    (user drivers can override it)
> > * improve FFA_PARTITION_INFO_GET implementation
> >    (clients no longer need to calloc a buffer)
> > * remove reparenting by making the sandbox emulator parent of the FF-A device in the DT
> > * improve argument checks for the armffa command
> > * address nits
> > 
...
> > Cc: Tom Rini <trini@konsulko.com>
> > Cc: Simon Glass <sjg@chromium.org>
> 
> A gentle reminder about the v12 patchset.
> 
> Your feedback is more than welcome :)

Could you please provide a feedback about the v12 patchset ?

Most of the patches are generic.

I'm gonna address Ilias comment for patch #9 with your future comments.

Your review is very much appreciated.

Kind regards
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v12 00/10] introduce Arm FF-A support
  2023-06-06 11:56                                                                                               ` Abdellatif El Khlifi
@ 2023-06-06 13:48                                                                                                 ` Tom Rini
  2023-06-16 15:28                                                                                                   ` [PATCH v13 " Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-06-06 13:48 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: sjg, nd, u-boot, ilias.apalodimas

[-- Attachment #1: Type: text/plain, Size: 4228 bytes --]

On Tue, Jun 06, 2023 at 12:56:28PM +0100, Abdellatif El Khlifi wrote:
> On Mon, May 22, 2023 at 10:13:20AM +0100, Abdellatif El Khlifi wrote:
> 
> Hi Simon, Tom,
> 
> > Hi Simon,
> > 
> > > Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> > > 
> > > FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> > > communicate with each other. A partition could be a VM in the Normal or Secure world, an
> > > application in S-EL0, or a Trusted OS in S-EL1.
> > > 
> > > FF-A is a discoverable bus and similar to architecture features.
> > > FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> > > by the PSCI driver.
> > > 
> > >    => dm tree
> > > 
> > >     Class     Index  Probed  Driver                Name
> > >    -----------------------------------------------------------
> > >    ...
> > >     firmware      0  [ + ]   psci                      |-- psci
> > >     ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
> > >    ...
> > > 
> > > Clients are able to probe then use the FF-A bus by calling the DM class
> > > searching APIs (e.g: uclass_first_device).
> > > 
> > > This implementation of the specification provides support for Aarch64.
> > > 
> > > The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> > > 
> > >     - Discover the presence of secure partitions (SPs) of interest
> > >     - Access an SP's service through communication protocols
> > >       (e.g: EFI MM communication protocol)
> > > 
> > > The FF-A support provides the following features:
> > > 
> > >     - Being generic by design and can be used by any Arm 64-bit platform
> > >     - FF-A support can be compiled and used without EFI
> > >     - Support for SMCCCv1.2 x0-x17 registers
> > >     - Support for SMC32 calling convention
> > >     - Support for 32-bit and 64-bit FF-A direct messaging
> > >     - Support for FF-A MM communication (compatible with EFI boot time)
> > >     - Enabling FF-A and MM communication in Corstone1000 platform as a use case
> > >     - 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.
> > >     - Sandbox FF-A test cases.
> > >     - A new command called armffa is provided as an example of how to access the
> > >       FF-A bus
> > > 
> > > For more details about the FF-A support please refer to [B] and refer to [C] for
> > > how to use the armffa command.
> > > 
> > > Please find at [D] an example of the expected boot logs when enabling
> > > FF-A support for a platform. In this example the platform is
> > > Corstone1000. But it can be any Arm 64-bit platform.
> > > 
> > > Changelog of the major changes:
> > > ===========================
> > > 
> > > v12:
> > > 
> > > * remove the global variable (dscvry_info), use uc_priv instead
> > > * replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
> > >    (user drivers can override it)
> > > * improve FFA_PARTITION_INFO_GET implementation
> > >    (clients no longer need to calloc a buffer)
> > > * remove reparenting by making the sandbox emulator parent of the FF-A device in the DT
> > > * improve argument checks for the armffa command
> > > * address nits
> > > 
> ...
> > > Cc: Tom Rini <trini@konsulko.com>
> > > Cc: Simon Glass <sjg@chromium.org>
> > 
> > A gentle reminder about the v12 patchset.
> > 
> > Your feedback is more than welcome :)
> 
> Could you please provide a feedback about the v12 patchset ?
> 
> Most of the patches are generic.
> 
> I'm gonna address Ilias comment for patch #9 with your future comments.
> 
> Your review is very much appreciated.

I've been waiting for Ilias to be happy with the series and then I'll
pick it up for -next.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v13 00/10] introduce Arm FF-A support
  2023-06-06 13:48                                                                                                 ` Tom Rini
@ 2023-06-16 15:28                                                                                                   ` Abdellatif El Khlifi
  2023-06-16 15:28                                                                                                     ` [PATCH v13 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                                                                                       ` (9 more replies)
  0 siblings, 10 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-06-16 15:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, nd, sjg, u-boot,
	achin.gupta, jens.wiklander, xueliang.zhong, Drew.Reed,
	Rob Herring, Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].

FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
communicate with each other. A partition could be a VM in the Normal or Secure world, an
application in S-EL0, or a Trusted OS in S-EL1.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

   => dm tree

    Class     Index  Probed  Driver                Name
   -----------------------------------------------------------
   ...
    firmware      0  [ + ]   psci                      |-- psci
    ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
   ...

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

This implementation of the specification provides support for Aarch64.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

    - Discover the presence of secure partitions (SPs) of interest
    - Access an SP's service through communication protocols
      (e.g: EFI MM communication protocol)

The FF-A support provides the following features:

    - Being generic by design and can be used by any Arm 64-bit platform
    - FF-A support can be compiled and used without EFI
    - Support for SMCCCv1.2 x0-x17 registers
    - Support for SMC32 calling convention
    - Support for 32-bit and 64-bit FF-A direct messaging
    - Support for FF-A MM communication (compatible with EFI boot time)
    - Enabling FF-A and MM communication in Corstone1000 platform as a use case
    - 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.
    - Sandbox FF-A test cases.
    - A new command called armffa is provided as an example of how to access the
      FF-A bus

For more details about the FF-A support please refer to [B] and refer to [C] for
how to use the armffa command.

Please find at [D] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of changes:
===========================

v13:

Ilias:
    * remove FF-A and Optee ifdefs in efi_variable_tee.c
    * doc minor change: specify in the readme that the user
       should call ffa_rxtx_unmap() driver operation to unmap
       the RX/TX buffers on demand.

v12: [12]

* remove the global variable (dscvry_info), use uc_priv instead
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* remove reparenting by making the sandbox emulator parent of the FF-A device in the DT
* improve argument checks for the armffa command
* address nits

v11: [11]

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* use U_BOOT_CMD_WITH_SUBCMDS for armffa command
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device
* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* use ut_asserteq_mem() in uuid_str_to_le_bin test case
* address nits

v10: [10]

* provide the FF-A driver operations through the Uclass (arm-ffa-uclass.c)
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c renamed from core.c)
* split the FF-A sandbox support into an emulator (ffa-emul-uclass.c) and a driver (sandbox_ffa.c)
* use the FF-A driver Uclass operations by clients (armffa command, tests, MM comms)
* use uclass_first_device to search and probe the FF-A device (whether it is on Arm or on sandbox)
* address nits

v9: [9]

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
* align FF-A sandbox driver with FF-A discovery through DM
* use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
* add documentation for the armffa command: doc/usage/cmd/armffa.rst
* introduce testcase for uuid_str_to_le_bin

v8: [8]

* pass the FF-A bus device to the bus operations
* isolate the compilation choices between FF-A and OP-TEE
* drop OP-TEE configs from Corstone-1000 defconfig
* make ffa_get_partitions_info() second argument to be an SP count in both
  modes

v7: [7]

* add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v6: [6]

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

List of previous patches:

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
[7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
[8]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
[9]: https://lore.kernel.org/all/20230310141016.137986-1-abdellatif.elkhlifi@arm.com/
[10]: https://lore.kernel.org/all/20230328161157.219375-1-abdellatif.elkhlifi@arm.com/
[11]: https://lore.kernel.org/all/20230412094245.44674-1-abdellatif.elkhlifi@arm.com/
[12]: https://lore.kernel.org/all/20230512121044.111574-1-abdellatif.elkhlifi@arm.com/

More details:

[A]: https://developer.arm.com/documentation/den0077/latest/
[B]: doc/arch/arm64.ffa.rst
[C]: doc/usage/cmd/armffa.rst
[D]: example of boot logs when enabling FF-A

```
   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64

   DRAM:  2 GiB
   Arm FF-A framework discovery
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   ...
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   EFI: MM partition ID 0x8003
   ...
   EFI stub: Booting Linux Kernel...
   ...
   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
   Machine model: ARM Corstone1000 FPGA MPS3 board
```

Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (10):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce uuid_str_to_le_bin function
  lib: uuid: introduce testcase for uuid_str_to_le_bin
  arm_ffa: introduce Arm FF-A support
  arm_ffa: introduce armffa command
  arm_ffa: introduce sandbox FF-A support
  arm_ffa: introduce sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   18 +
 arch/arm/cpu/armv8/smccc-call.S               |   57 +-
 arch/arm/lib/asm-offsets.c                    |   16 +
 arch/sandbox/dts/sandbox.dtsi                 |    9 +
 arch/sandbox/dts/test.dts                     |    8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |   72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        |  121 ++
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    1 +
 cmd/armffa.c                                  |  196 +++
 configs/corstone1000_defconfig                |    1 +
 configs/sandbox64_defconfig                   |    1 +
 configs/sandbox_defconfig                     |    1 +
 doc/arch/arm64.ffa.rst                        |  261 ++++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox/sandbox.rst                  |    1 +
 doc/usage/cmd/armffa.rst                      |   93 ++
 doc/usage/index.rst                           |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   42 +
 drivers/firmware/arm-ffa/Makefile             |   16 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 drivers/firmware/arm-ffa/ffa-emul-uclass.c    |  720 +++++++++++
 drivers/firmware/arm-ffa/sandbox_ffa.c        |  110 ++
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/configs/corstone1000.h                |   15 +-
 include/dm/uclass-id.h                        |    7 +
 include/linux/arm-smccc.h                     |   45 +
 include/mm_communication.h                    |   13 +
 include/uuid.h                                |   15 +
 lib/efi_loader/Kconfig                        |   16 +-
 lib/efi_loader/efi_variable_tee.c             |  260 +++-
 lib/uuid.c                                    |   48 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   33 +
 test/dm/Makefile                              |    3 +-
 test/dm/ffa.c                                 |  261 ++++
 test/lib/Makefile                             |    1 +
 test/lib/uuid.c                               |   41 +
 42 files changed, 4135 insertions(+), 11 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 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 doc/usage/cmd/armffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/lib/uuid.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v13 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-06-16 15:28                                                                                                   ` [PATCH v13 " Abdellatif El Khlifi
@ 2023-06-16 15:28                                                                                                     ` Abdellatif El Khlifi
  2023-06-20 14:05                                                                                                       ` Ilias Apalodimas
  2023-06-16 15:28                                                                                                     ` [PATCH v13 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
                                                                                                                       ` (8 subsequent siblings)
  9 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-06-16 15:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, nd, sjg, u-boot,
	achin.gupta, jens.wiklander, xueliang.zhong, Drew.Reed

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>

---

Changelog:
===============

v9:

* update the copyright string

v7:

* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

 arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
 arch/arm/lib/asm-offsets.c      | 16 +++++++++
 include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..93f66d3366 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,7 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
- */
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+*/
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
 #include <generated/asm-offsets.h>
@@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 6de0ce9152..181a8ac4c2 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,11 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * 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>
@@ -90,6 +95,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#ifdef CONFIG_ARM64
+	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..f44e9e8f93 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +74,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v13 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2023-06-16 15:28                                                                                                   ` [PATCH v13 " Abdellatif El Khlifi
  2023-06-16 15:28                                                                                                     ` [PATCH v13 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-06-16 15:28                                                                                                     ` Abdellatif El Khlifi
  2023-06-16 15:28                                                                                                     ` [PATCH v13 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
                                                                                                                       ` (7 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-06-16 15:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, nd, sjg, u-boot,
	achin.gupta, jens.wiklander, xueliang.zhong, Drew.Reed

convert UUID string to little endian binary data

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
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>

---

Changelog:
===============

v9:

* add a full function prototype description in uuid.h

v8:

* use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

 include/uuid.h | 15 +++++++++++++++
 lib/uuid.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..89b93e642b 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,10 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +48,15 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ * Return:
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 96e1af3c8b..45f325d964 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * 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>
@@ -354,6 +358,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16;
+	u32 tmp32;
+	u64 tmp64;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+	memcpy(uuid_bin, &tmp32, 4);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16));
+	memcpy(uuid_bin + 10, &tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v13 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-06-16 15:28                                                                                                   ` [PATCH v13 " Abdellatif El Khlifi
  2023-06-16 15:28                                                                                                     ` [PATCH v13 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2023-06-16 15:28                                                                                                     ` [PATCH v13 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2023-06-16 15:28                                                                                                     ` Abdellatif El Khlifi
  2023-06-20 10:27                                                                                                       ` Simon Glass
  2023-06-16 15:28                                                                                                     ` [PATCH v13 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                       ` (6 subsequent siblings)
  9 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-06-16 15:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, nd, sjg, u-boot,
	achin.gupta, jens.wiklander, xueliang.zhong, Drew.Reed

provide a test case

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Simon Glass <sjg@chromium.org>

---

Changelog:
===============

v11:

* use ut_asserteq_mem()

 MAINTAINERS       |  5 +++++
 test/lib/Makefile |  1 +
 test/lib/uuid.c   | 41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)
 create mode 100644 test/lib/uuid.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 228d8af433..b9e26cac82 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1632,3 +1632,8 @@ S:	Maintained
 F:	arch/arm/dts/ls1021a-twr-u-boot.dtsi
 F:	drivers/crypto/fsl/
 F:	include/fsl_sec.h
+
+UUID testing
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	test/lib/uuid.c
diff --git a/test/lib/Makefile b/test/lib/Makefile
index e0bd9e04e8..e75a263e6a 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_AES) += test_aes.o
 obj-$(CONFIG_GETOPT) += getopt.o
 obj-$(CONFIG_CRC8) += test_crc8.o
 obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o
+obj-$(CONFIG_LIB_UUID) += uuid.o
 else
 obj-$(CONFIG_SANDBOX) += kconfig_spl.o
 endif
diff --git a/test/lib/uuid.c b/test/lib/uuid.c
new file mode 100644
index 0000000000..e24331a136
--- /dev/null
+++ b/test/lib/uuid.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <uuid.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* test UUID */
+#define TEST_SVC_UUID	"ed32d533-4209-99e6-2d72-cdd998a79cc0"
+
+#define UUID_SIZE 16
+
+/* The UUID binary data (little-endian format) */
+static const u8 ref_uuid_bin[UUID_SIZE] = {
+	0x33, 0xd5, 0x32, 0xed,
+	0x09, 0x42, 0xe6, 0x99,
+	0x72, 0x2d, 0xc0, 0x9c,
+	0xa7, 0x98, 0xd9, 0xcd
+};
+
+static int lib_test_uuid_to_le(struct unit_test_state *uts)
+{
+	const char *uuid_str = TEST_SVC_UUID;
+	u8 ret_uuid_bin[UUID_SIZE] = {0};
+
+	ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin));
+	ut_asserteq_mem(ref_uuid_bin, ret_uuid_bin, UUID_SIZE);
+
+	return 0;
+}
+
+LIB_TEST(lib_test_uuid_to_le, 0);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v13 04/10] arm_ffa: introduce Arm FF-A support
  2023-06-16 15:28                                                                                                   ` [PATCH v13 " Abdellatif El Khlifi
                                                                                                                       ` (2 preceding siblings ...)
  2023-06-16 15:28                                                                                                     ` [PATCH v13 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-06-16 15:28                                                                                                     ` Abdellatif El Khlifi
  2023-06-20 10:27                                                                                                       ` Simon Glass
  2023-06-16 15:28                                                                                                     ` [PATCH v13 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                                                                                       ` (5 subsequent siblings)
  9 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-06-16 15:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, nd, sjg, u-boot,
	achin.gupta, jens.wiklander, xueliang.zhong, Drew.Reed,
	Heinrich Schuchardt

Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- ffa_partition_info_get
- ffa_sync_send_receive
- ffa_rxtx_unmap

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 please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v13:

* doc minor change: specify in the readme that the user
   should call ffa_rxtx_unmap() driver operation to unmap
   the RX/TX buffers on demand.

v12:

* remove dscvry_info
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* address nits

v11:

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* pass dev as an argument of arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* add emul field in struct ffa_discovery_info
* address nits

v10:

* provide the driver operations through the Uclass
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c)
* rename core.c to arm-ffa.c
* address nits

v9:

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding

v8:

* make ffa_get_partitions_info() second argument to be an SP count in both
  modes
* update ffa_bus_prvdata_get() to return a pointer rather than a pointer
  address
* remove packing from ffa_partition_info and ffa_send_direct_data structures
* pass the FF-A bus device to the bus operations

v7:

* add support for 32-bit direct messaging
* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* improve the declaration of error handling mapping
* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the U-Boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the U-Boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

 MAINTAINERS                                   |    8 +
 doc/arch/arm64.ffa.rst                        |  238 ++++
 doc/arch/index.rst                            |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   36 +
 drivers/firmware/arm-ffa/Makefile             |    8 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |   14 +
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/dm/uclass-id.h                        |    6 +
 13 files changed, 1941 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h

diff --git a/MAINTAINERS b/MAINTAINERS
index b9e26cac82..43603522fd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,6 +266,14 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+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>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..4f817f053c
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,238 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Support
+================
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
+communicate with each other. A partition could be a VM in the Normal or Secure world, an
+application in S-EL0, or a Trusted OS in S-EL1.
+
+The U-Boot FF-A support (the bus) implements the interfaces to communicate
+with partitions in the Secure world aka Secure partitions (SPs).
+
+The FF-A support specifically focuses on communicating with SPs that
+isolate portions of EFI runtime services that must run in a protected
+environment which is inaccessible by the Host OS or Hypervisor.
+Examples of such services are set/get variables.
+
+The FF-A support uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+At this stage of development only EFI boot-time services are supported.
+Runtime support will be added in future developments.
+
+The U-Boot FF-A support provides the following parts:
+
+- A Uclass driver providing generic FF-A methods.
+- An Arm FF-A device driver providing Arm-specific methods and reusing the Uclass methods.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the U-Boot FF-A support relies on
+`FF-A v1.0 specification`_ and uses SMC32 calling convention which
+means using the first 32-bit data of the Xn registers.
+
+At this stage we only need the FF-A v1.0 features.
+
+The FF-A support has been tested with OP-TEE which supports SMC32 calling
+convention.
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A support uses 64-bit registers as per `SMC Calling Convention v1.2 specification`_.
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+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.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers.
+Then, an SMC instruction is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-Boot Arm FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs.
+
+FF-A bus discovery on Arm 64-bit platforms
+---------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
+an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
+This discovery mechanism is performed by the PSCI driver.
+
+The PSCI driver comes with a PSCI device tree node which is the root node for all
+architecture features including FF-A bus.
+
+::
+
+   => dm tree
+
+    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.
+
+In case of FF-A, the callback is arm_ffa_is_supported() which tries to discover the
+FF-A framework by querying the FF-A framework version from secure world using
+FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
+mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver
+with the device using device_bind_driver().
+
+At this stage the FF-A bus is registered with the DM and can be interacted with using
+the DM APIs.
+
+Clients are able to probe then use the FF-A bus by calling uclass_first_device().
+Please refer to the armffa command implementation as an example of how to probe
+and interact with the FF-A bus.
+
+When calling uclass_first_device(), the FF-A driver is probed and ends up calling
+ffa_do_probe() provided by the Uclass which does the following:
+
+    - saving the FF-A framework version in uc_priv
+    - querying from secure world the u-boot endpoint ID
+    - querying from secure world the supported features of FFA_RXTX_MAP
+    - mapping the RX/TX buffers
+    - querying from secure world all the partitions information
+
+When one of the above actions fails, probing fails and the driver stays not active
+and can be probed again if needed.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must query the SPs they are looking for
+during EFI boot-time mode using the service UUID.
+
+The RX/TX buffers are only available at EFI boot-time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped before EFI runtime mode starts.
+The driver provides a bus operation for that called ffa_rxtx_unmap().
+
+The user should call ffa_rxtx_unmap() to unmap the RX/TX buffers when required
+(e.g: at efi_exit_boot_services()).
+
+The Linux kernel allocates its own RX/TX buffers. To be able to register these kernel buffers
+with secure world, the U-Boot's RX/TX buffers should be unmapped before EFI runtime starts.
+
+When invoking FF-A direct messaging, clients should specify which ABI protocol
+they want to use (32-bit vs 64-bit). Selecting the protocol means using
+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
+The calling convention between U-Boot and the secure world stays the same: SMC32.
+
+Requirements for user drivers
+-------------------------------------
+
+Users who want to implement their custom FF-A device driver while reusing the FF-A Uclass can do so
+by implementing their own invoke_ffa_fn() in the user driver.
+
+The bus driver layer
+------------------------------
+
+FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c
+
+The following features are provided:
+
+- Support for the 32-bit version of the following ABIs:
+
+    - FFA_VERSION
+    - FFA_ID_GET
+    - FFA_FEATURES
+    - FFA_PARTITION_INFO_GET
+    - FFA_RXTX_UNMAP
+    - FFA_RX_RELEASE
+    - FFA_RUN
+    - FFA_ERROR
+    - FFA_SUCCESS
+    - FFA_INTERRUPT
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Support for the 64-bit version of the following ABIs:
+
+    - FFA_RXTX_MAP
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, FF-A support takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- FF-A support provides driver operations to be used by upper layers:
+
+    - ffa_partition_info_get
+    - ffa_sync_send_receive
+    - ffa_rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+Example of boot logs with FF-A enabled
+--------------------------------------
+
+For example, when using FF-A with Corstone-1000 the logs are as follows:
+
+::
+
+   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64
+
+   DRAM:  2 GiB
+   Arm FF-A framework discovery
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   ...
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   EFI: MM partition ID 0x8003
+   ...
+   EFI stub: Booting Linux Kernel...
+   ...
+   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
+   Machine model: ARM Corstone1000 FPGA MPS3 board
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+
+.. _`FF-A v1.0 specification`: https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e
+.. _`SMC Calling Convention v1.2 specification`: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index b8da4b8c8e..2f916f4026 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Makefile b/drivers/Makefile
index 29be78a3f2..6094fac50d 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -114,6 +114,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index eae1c8ddc9..8789b1ea14 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
 	  the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
 	  services if any and reported as supported by the SMCCC firmware.
 
+source "drivers/firmware/arm-ffa/Kconfig"
 source "drivers/firmware/scmi/Kconfig"
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..9200c8028b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select ARM_SMCCC_FEATURES
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
+	  FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
+	  by the PSCI driver.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  The FF-A support on U-Boot  takes care of all the interactions between Normal
+	  world and Secure World.
+
+	  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
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..11b1766285
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,8 @@
+# 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>
+
+obj-y += arm-ffa-uclass.o arm-ffa.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..ffa9d81fa7
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,1065 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	[NOT_SUPPORTED] = -EOPNOTSUPP,
+	[INVALID_PARAMETERS] = -EINVAL,
+	[NO_MEMORY] = -ENOMEM,
+	[BUSY] = -EBUSY,
+	[INTERRUPTED] = -EINTR,
+	[DENIED] = -EACCES,
+	[RETRY] = -EAGAIN,
+	[ABORTED] = -ECANCELED,
+};
+
+static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			[NO_MEMORY] =
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			[BUSY] =
+			"BUSY: RX buffer of the caller is not free",
+			[DENIED] =
+			"DENIED: Callee is not in a state to handle this request",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			[DENIED] =
+			"DENIED: Caller did not have ownership of the RX buffer",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			[NO_MEMORY] =
+			"NO_MEMORY: Not enough memory",
+			[DENIED] =
+			"DENIED: Buffer pair already registered",
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno() - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+static int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* Map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+static int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* Map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	log_err("%s\n", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/* FF-A ABIs implementation (U-Boot side) */
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void __weak invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+}
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	log_info("FF-A driver %d.%d\nFF-A framework %d.%d\n",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) {
+		log_info("FF-A versions are compatible\n");
+
+		if (dev) {
+			uc_priv = dev_get_uclass_priv(dev);
+			if (uc_priv)
+				uc_priv->fwk_version = res.a0;
+		}
+
+		return 0;
+	}
+
+	log_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id() - FFA_ID_GET handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		uc_priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		log_debug("FF-A endpoint ID is %u\n", uc_priv->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt() - set the minimum number of pages in each of the RX/TX buffers
+ * @dev: The FF-A bus device
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * Set the minimum number of pages in each of the RX/TX buffers in uc_priv
+ *
+ * Return:
+ *
+ * rxtx_min_pages field contains the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	switch (prop_field) {
+	case RXTX_4K:
+		uc_priv->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		uc_priv->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		uc_priv->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		log_err("RX/TX buffer size not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features_hdlr() - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_FEATURES FF-A function to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers() - free the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Free the RX/TX buffers
+ */
+static void ffa_free_rxtx_buffers(struct udevice *dev)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Freeing FF-A RX/TX buffers\n");
+
+	if (uc_priv->pair.rxbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+	}
+
+	if (uc_priv->pair.txbuf) {
+		free(uc_priv->pair.txbuf);
+		uc_priv->pair.txbuf = NULL;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers() - allocate the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ * The size of the memory allocated is the minimum allowed.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(struct udevice *dev)
+{
+	u64 bytes;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Using %lu 4KB page(s) for FF-A RX/TX buffers size\n",
+		  uc_priv->pair.rxtx_min_pages);
+
+	bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 * Assumption: Memory allocated with memalign is always physically contiguous
+	 */
+
+	uc_priv->pair.rxbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.rxbuf) {
+		log_err("failure to allocate RX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A RX buffer at virtual address %p\n", uc_priv->pair.rxbuf);
+
+	uc_priv->pair.txbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.txbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+		log_err("failure to allocate the TX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A TX buffer at virtual address %p\n", uc_priv->pair.txbuf);
+
+	/* Make sure the buffers are cleared before use */
+	memset(uc_priv->pair.rxbuf, 0, bytes);
+	memset(uc_priv->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers_hdlr() - FFA_RXTX_MAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_MAP FF-A function to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	ret = ffa_alloc_rxtx_buffers(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 * no need to convert from virtual to physical
+	 */
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = map_to_sysmem(uc_priv->pair.txbuf),
+			.a2 = map_to_sysmem(uc_priv->pair.rxbuf),
+			.a3 = uc_priv->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		log_debug("FF-A RX/TX buffers mapped\n");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers(dev);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_UNMAP FF-A function to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	log_debug("unmapping FF-A RX/TX buffers\n");
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers(dev);
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer_hdlr() - FFA_RX_RELEASE handler function
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_RX_RELEASE FF-A function to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical() - check whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * Used by ffa_read_partitions_info to search for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+static bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+				   const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info() - read queried partition data
+ * @dev: The FF-A bus device
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * Read the partitions information returned by the FFA_PARTITION_INFO_GET and saves it in uc_priv
+ *
+ * Return:
+ *
+ * uc_priv is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(struct udevice *dev, u32 count,
+				    struct ffa_partition_uuid *part_uuid)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	if (!count) {
+		log_err("no partition detected\n");
+		return -ENODATA;
+	}
+
+	log_debug("Reading FF-A partitions data from the RX buffer\n");
+
+	if (!part_uuid) {
+		/* Querying information of all partitions */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			log_err("partitions data size exceeds the RX buffer size:\n");
+			log_err("    sizes in bytes: data %llu , RX buffer %llu\n",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		uc_priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO);
+		if (!uc_priv->partitions.descs) {
+			log_err("cannot  allocate partitions data buffer\n");
+			return -ENOMEM;
+		}
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			uc_priv->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			log_debug("FF-A partition ID %x : info cached\n",
+				  uc_priv->partitions.descs[desc_idx].info.id);
+		}
+
+		uc_priv->partitions.count = count;
+
+		log_debug("%d FF-A partition(s) found and cached\n", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		/*
+		 * Search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/* Search the current ID in the cached partitions */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < uc_priv->partitions.count;
+			     cached_desc_idx++) {
+				/* Save the UUID */
+				if (uc_priv->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					uc_priv->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info() - invoke FFA_PARTITION_INFO_GET and save partitions data
+ * @dev: The FF-A bus device
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * Execute the FFA_PARTITION_INFO_GET to query the partitions data.
+ * Then, call ffa_read_partitions_info to save the data in uc_priv.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid);
+			if (ret) {
+				log_err("failed reading SP(s) data , err (%d)\n", ret);
+				ffa_release_rx_buffer_hdlr(dev);
+				return -EINVAL;
+			}
+		}
+
+		/* Return the SP count (when querying using a UUID) */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer_hdlr(dev);
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET FF-A function to query the partition information
+ * from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * If the partition(s) matching the UUID found, the partition(s) information and the
+ * number are returned.
+ * If no partition matching the UUID is found in the cached area, a new FFA_PARTITION_INFO_GET
+ * call is issued.
+ * If not done yet, the UUID is updated in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	u32 i;
+	struct ffa_partition_uuid part_uuid = {0};
+	struct ffa_priv *uc_priv;
+	struct ffa_partition_desc *rx_descs;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs) {
+		log_err("no partition installed\n");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		log_err("no UUID provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_count) {
+		log_err("no count argument provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_descs) {
+		log_err("no info argument provided\n");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		log_err("invalid UUID\n");
+		return -EINVAL;
+	}
+
+	log_debug("Searching FF-A partitions using the provided UUID\n");
+
+	*sp_count = 0;
+	*sp_descs = uc_priv->pair.rxbuf;
+	rx_descs = *sp_descs;
+
+	/* Search in the cached partitions */
+	for (i = 0; i < uc_priv->partitions.count; i++)
+		if (ffa_uuid_are_identical(&uc_priv->partitions.descs[i].sp_uuid,
+					   &part_uuid)) {
+			log_debug("FF-A partition ID %x matches the provided UUID\n",
+				  uc_priv->partitions.descs[i].info.id);
+
+			(*sp_count)++;
+			*rx_descs++ = uc_priv->partitions.descs[i];
+			}
+
+	if (!(*sp_count)) {
+		int ret;
+
+		log_debug("No FF-A partition found. Querying framework ...\n");
+
+		ret = ffa_query_partitions_info(dev, &part_uuid, sp_count);
+
+		if (!ret) {
+			log_debug("Number of FF-A partition(s) matching the UUID: %d\n", *sp_count);
+
+			if (*sp_count)
+				ret = ffa_get_partitions_info_hdlr(dev, uuid_str, sp_count,
+								   sp_descs);
+			else
+				ret = -ENODATA;
+		}
+
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info() - Query and saves all secure partitions data
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_PARTITION_INFO_GET FF-A function to query from secure world
+ * all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in uc_priv
+ * and we keep the UUID field empty (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * Called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(struct udevice *dev)
+{
+	return ffa_query_partitions_info(dev, NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Implement FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u64 req_mode, resp_mode;
+	struct ffa_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* No partition installed */
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs)
+		return -ENODEV;
+
+	if (is_smc64) {
+		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+	} else {
+		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = req_mode,
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == resp_mode) {
+		/* Message sent with response extract the return data */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/* FF-A driver operations (used by clients for communicating with FF-A)*/
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Driver operation for FFA_PARTITION_INFO_GET.
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->partition_info_get)
+		return -ENOSYS;
+
+	return ops->partition_info_get(dev, uuid_str, sp_count, sp_descs);
+}
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Driver operation for FFA_MSG_SEND_DIRECT_{REQ,RESP}.
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->sync_send_receive)
+		return -ENOSYS;
+
+	return ops->sync_send_receive(dev, dst_part_id, msg, is_smc64);
+}
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * @dev: The FF-A bus device
+ *
+ * Driver operation for FFA_RXTX_UNMAP.
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_rxtx_unmap(struct udevice *dev)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->rxtx_unmap)
+		return -ENOSYS;
+
+	return ops->rxtx_unmap(dev);
+}
+
+/**
+ * ffa_do_probe() - probing FF-A framework
+ * @dev:	the FF-A bus device (arm_ffa)
+ *
+ * Probing is triggered on demand by clients searching for the uclass.
+ * At probe level the following actions are done:
+ *	- saving the FF-A framework version in uc_priv
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in uc_priv.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_do_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_endpoint_id(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_cache_partitions_info(dev);
+	if (ret) {
+		ffa_unmap_rxtx_buffers_hdlr(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+UCLASS_DRIVER(ffa) = {
+	.name			= "ffa",
+	.id			= UCLASS_FFA,
+	.pre_probe		= ffa_do_probe,
+	.pre_remove		= ffa_unmap_rxtx_buffers_hdlr,
+	.per_device_auto	= sizeof(struct ffa_priv)
+};
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
new file mode 100644
index 0000000000..68df75bd9e
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -0,0 +1,104 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <linux/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * 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 low level SMC assembly function
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * arm_ffa_discover() - perform FF-A discovery
+ * @dev: The Arm FF-A bus device (arm_ffa)
+ * 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:
+ *
+ * true on success. Otherwise, false.
+ */
+static bool arm_ffa_discover(struct udevice *dev)
+{
+	int ret;
+
+	log_info("Arm FF-A framework discovery\n");
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/**
+ * arm_ffa_is_supported() - FF-A bus discovery callback
+ * @invoke_fn: legacy SMC invoke function (not used)
+ *
+ * Perform FF-A discovery by calling arm_ffa_discover().
+ * Discovery is performed by querying the FF-A framework version from
+ * secure world using the FFA_VERSION ABI.
+ *
+ * The FF-A driver is registered as an SMCCC feature driver. So, features discovery
+ * callbacks are called by the PSCI driver (PSCI device is the SMCCC features
+ * root device).
+ *
+ * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
+ * So, the legacy SMC invocation is not used.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static bool arm_ffa_is_supported(void (*invoke_fn)(ulong a0, ulong a1,
+						   ulong a2, ulong a3,
+						   ulong a4, ulong a5,
+						   ulong a6, ulong a7,
+						   struct arm_smccc_res *res))
+{
+	return arm_ffa_discover(NULL);
+}
+
+/* Arm FF-A driver operations */
+
+static const struct ffa_bus_ops 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,
+};
+
+/* Registering the FF-A driver as an SMCCC feature driver */
+
+ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
+	.driver_name = FFA_DRV_NAME,
+	.is_supported = arm_ffa_is_supported,
+};
+
+/* Declaring the FF-A driver under UCLASS_FFA */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.flags		= DM_REMOVE_OS_PREPARE,
+	.ops		= &ffa_ops,
+};
diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
new file mode 100644
index 0000000000..4338f9c9b1
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
@@ -0,0 +1,14 @@
+/* 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/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..db9b1be995
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,213 @@
+/* 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 __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
+ * @a1-4:	32-bit words access to the UUID data
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct ffa_send_direct_data {
+	ulong data0; /* w3/x3 */
+	ulong data1; /* w4/x4 */
+	ulong data2; /* w5/x5 */
+	ulong data3; /* w6/x6 */
+	ulong data4; /* w7/x7 */
+};
+
+struct udevice;
+
+/**
+ * struct ffa_bus_ops - Operations for FF-A
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
+				  u32 *sp_count, struct ffa_partition_desc **sp_descs);
+	int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg,
+				 bool is_smc64);
+	int (*rxtx_unmap)(struct udevice *dev);
+};
+
+#define ffa_get_ops(dev)        ((struct ffa_bus_ops *)(dev)->driver->ops)
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ */
+int ffa_rxtx_unmap(struct udevice *dev);
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The arm_ffa bus device
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev);
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The arm_ffa bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+struct ffa_priv;
+
+/**
+ * ffa_set_smc_conduit() - Set the SMC conduit
+ * @dev: The FF-A bus device
+ *
+ * Selects the SMC conduit by setting the FF-A ABI invoke function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_set_smc_conduit(struct udevice *dev);
+
+#endif
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
new file mode 100644
index 0000000000..d564c33c64
--- /dev/null
+++ b/include/arm_ffa_priv.h
@@ -0,0 +1,246 @@
+/* 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 __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <mapmem.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+
+/* This header is exclusively used by the FF-A Uclass and FF-A driver(s) */
+
+/* Arm FF-A driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* The FF-A SMC function definitions */
+
+#if CONFIG_IS_ENABLED(SANDBOX)
+
+/* Providing Arm SMCCC declarations to sandbox */
+
+/**
+ * struct sandbox_smccc_1_2_regs - emulated SMC call arguments or results
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct sandbox_smccc_1_2_regs {
+	ulong a0;
+	ulong a1;
+	ulong a2;
+	ulong a3;
+	ulong a4;
+	ulong a5;
+	ulong a6;
+	ulong a7;
+	ulong a8;
+	ulong a9;
+	ulong a10;
+	ulong a11;
+	ulong a12;
+	ulong a13;
+	ulong a14;
+	ulong a15;
+	ulong a16;
+	ulong a17;
+};
+
+typedef struct sandbox_smccc_1_2_regs ffa_value_t;
+
+#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))
+
+#else
+/* CONFIG_ARM64 */
+#include <linux/arm-smccc.h>
+typedef struct arm_smccc_1_2_regs ffa_value_t;
+#endif
+
+/* Defining the function pointer type for the function executing the FF-A ABIs */
+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)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR                 = 0x60,
+	FFA_SUCCESS               = 0x61,
+	FFA_INTERRUPT             = 0x62,
+	FFA_VERSION               = 0x63,
+	FFA_FEATURES              = 0x64,
+	FFA_RX_RELEASE            = 0x65,
+	FFA_RXTX_MAP              = 0x66,
+	FFA_RXTX_UNMAP            = 0x67,
+	FFA_PARTITION_INFO_GET    = 0x68,
+	FFA_ID_GET                = 0x69,
+	FFA_RUN                   = 0x6d,
+	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
+	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
+
+	/* To be updated when adding new FFA IDs */
+	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
+	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
+};
+
+enum ffa_abi_errcode {
+	NOT_SUPPORTED = 1,
+	INVALID_PARAMETERS,
+	NO_MEMORY,
+	BUSY,
+	INTERRUPTED,
+	DENIED,
+	RETRY,
+	ABORTED,
+	MAX_NUMBER_FFA_ERR
+};
+
+extern int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR];
+
+/* Container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Hosts the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	void *rxbuf; /* Virtual address returned by memalign */
+	void *txbuf; /* Virtual address returned by memalign */
+	size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */
+};
+
+struct ffa_partition_desc;
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * Contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* Virtual address */
+};
+
+/**
+ * struct ffa_priv - the driver private data structure
+ *
+ * @fwk_version:	FF-A framework version
+ * @emul:	FF-A sandbox emulator
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ *
+ * The device private data structure containing all the
+ * data read from secure world.
+ */
+struct ffa_priv {
+	u32 fwk_version;
+	struct udevice *emul;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+};
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev);
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 307ad6931c..3c6af2e3d2 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,11 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -57,6 +62,7 @@ enum uclass_id {
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_EXTCON,		/* External Connector Class */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v13 05/10] arm_ffa: introduce armffa command
  2023-06-16 15:28                                                                                                   ` [PATCH v13 " Abdellatif El Khlifi
                                                                                                                       ` (3 preceding siblings ...)
  2023-06-16 15:28                                                                                                     ` [PATCH v13 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-06-16 15:28                                                                                                     ` Abdellatif El Khlifi
  2023-06-20 10:27                                                                                                       ` Simon Glass
  2023-06-20 14:25                                                                                                       ` Ilias Apalodimas
  2023-06-16 15:28                                                                                                     ` [PATCH v13 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
                                                                                                                       ` (4 subsequent siblings)
  9 siblings, 2 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-06-16 15:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, nd, sjg, u-boot,
	achin.gupta, jens.wiklander, xueliang.zhong, Drew.Reed,
	Heinrich Schuchardt

Provide armffa command showcasing the use of the U-Boot FF-A support

armffa is a command showcasing how to invoke FF-A operations.
This provides a guidance to the client developers on how to
call the FF-A bus interfaces. The command also allows to gather secure
partitions information and ping these  partitions. The command is also
helpful in testing the communication with secure partitions.

For more details please refer to the command documentation [1].

[1]: doc/usage/cmd/armffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* add subcommands argument checks
* usage documentation: update command return codes
* remove calloc when querying SPs
* address nits

v11:

* use U_BOOT_CMD_WITH_SUBCMDS
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* address nits

v9:

* remove manual FF-A discovery and use DM
* use DM class APIs to probe and interact with the FF-A bus
* add doc/usage/cmd/armffa.rst

v8:

* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* adapt do_ffa_dev_list() following the recent update on
  uclass_first_device/uclass_next_device functions (they return void now)
* set armffa command to use 64-bit direct messaging

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

 MAINTAINERS                      |   2 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   1 +
 cmd/armffa.c                     | 196 +++++++++++++++++++++++++++++++
 doc/arch/arm64.ffa.rst           |   7 ++
 doc/usage/cmd/armffa.rst         |  93 +++++++++++++++
 doc/usage/index.rst              |   1 +
 drivers/firmware/arm-ffa/Kconfig |   1 +
 8 files changed, 311 insertions(+)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/usage/cmd/armffa.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 43603522fd..0d960731cf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,7 +269,9 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+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
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 365371fb51..86af7bcc9e 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -934,6 +934,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the FF-A support
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index 6c37521b4e..7d20a85a46 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,7 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_2048) += 2048.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..fa268e9cb9
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,196 @@
+// 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 <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+#include <asm/io.h>
+
+/**
+ * ffa_get_dev() - Return the FF-A device
+ * @devp:	pointer to the FF-A device
+ *
+ * Search for the FF-A device.
+ *
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_dev(struct udevice **devp)
+{
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, devp);
+	if (ret) {
+		log_err("Cannot find FF-A bus device\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * do_ffa_getpart() - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query the secure partition information which the UUID is provided
+ * as an argument. The function uses the arm_ffa driver
+ * partition_info_get operation which implements FFA_PARTITION_INFO_GET
+ * ABI to retrieve the data. The input UUID string is expected to be in big
+ * endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	u32 i;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+
+	ret = ffa_partition_info_get(dev, argv[1], &count, &descs);
+	if (ret) {
+		log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	/* SPs found , show the partition information */
+	for (i = 0; i < count ; i++) {
+		log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
+			 descs[i].info.id,
+			 descs[i].info.exec_ctxt,
+			 descs[i].info.properties);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_ffa_ping() - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Send data to the secure partition which the ID is provided
+ * as an argument. Use the arm_ffa driver sync_send_receive operation
+ * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	errno = 0;
+	part_id = strtoul(argv[1], NULL, 16);
+
+	if (errno) {
+		log_err("Invalid partition ID\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	if (!ret) {
+		u8 cnt;
+
+		log_info("SP response:\n[LSB]\n");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			log_info("%llx\n", ((u64 *)&msg)[cnt]);
+		return CMD_RET_SUCCESS;
+	}
+
+	log_err("Sending direct request error (%d)\n", ret);
+	return CMD_RET_FAILURE;
+}
+
+/**
+ *do_ffa_devlist() - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query the device belonging to the UCLASS_FFA
+ * class.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	log_info("device name %s, dev %p, driver name %s, ops %p\n",
+		 dev->name,
+		(void *)map_to_sysmem(dev),
+		 dev->driver->name,
+		 (void *)map_to_sysmem(dev->driver->ops));
+
+	return CMD_RET_SUCCESS;
+}
+
+static char armffa_help_text[] =
+	"getpart <partition UUID>\n"
+	"       - lists the partition(s) info\n"
+	"ping <partition ID>\n"
+	"       - sends a data pattern to the specified partition\n"
+	"devlist\n"
+	"       - displays information about the FF-A device/driver\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
+			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
+			U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping),
+			U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist));
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 4f817f053c..aefd527447 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -205,6 +205,13 @@ The following features are provided:
 
 - FF-A bus can be compiled and used without EFI
 
+The armffa command
+-----------------------------------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke the driver operations.
+
+Please refer the command documentation at :doc:`../usage/cmd/armffa`
+
 Example of boot logs with FF-A enabled
 --------------------------------------
 
diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
new file mode 100644
index 0000000000..3d422686c1
--- /dev/null
+++ b/doc/usage/cmd/armffa.rst
@@ -0,0 +1,93 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+armffa command
+==============
+
+Synopsis
+--------
+
+::
+
+   armffa [sub-command] [arguments]
+
+   sub-commands:
+
+        getpart [partition UUID]
+
+            lists the partition(s) info
+
+        ping [partition ID]
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays information about the FF-A device/driver
+
+Description
+-----------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
+
+The command also allows to gather secure partitions information and ping these  partitions.
+
+The command is also helpful in testing the communication with secure partitions.
+
+Example
+-------
+
+The following examples are run on Corstone-1000 platform.
+
+* ping
+
+::
+
+   corstone1000# armffa ping 0x8003
+   SP response:
+   [LSB]
+   fffffffe
+   0
+   0
+   0
+   0
+
+* ping (failure case)
+
+::
+
+   corstone1000# armffa ping 0
+   Sending direct request error (-22)
+
+* getpart
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
+   Partition: id = 8003 , exec_ctxt 1 , properties 3
+
+* getpart (failure case)
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221
+   INVALID_PARAMETERS: Unrecognized UUID
+   Failure in querying partitions count (error code: -22)
+
+* devlist
+
+::
+
+   corstone1000# armffa devlist
+   device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98
+
+Configuration
+-------------
+
+The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
+
+Return value
+------------
+
+The return value $? is 0 (true) on success, 1 (false) on failure.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 84ef8a9a42..cfd438d88c 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -22,6 +22,7 @@ Shell commands
 
    cmd/acpi
    cmd/addrmap
+   cmd/armffa
    cmd/askenv
    cmd/base
    cmd/bdinfo
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index 9200c8028b..a7d5392859 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
 	depends on DM && ARM64
 	select ARM_SMCCC
 	select ARM_SMCCC_FEATURES
+	imply CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v13 06/10] arm_ffa: introduce sandbox FF-A support
  2023-06-16 15:28                                                                                                   ` [PATCH v13 " Abdellatif El Khlifi
                                                                                                                       ` (4 preceding siblings ...)
  2023-06-16 15:28                                                                                                     ` [PATCH v13 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-06-16 15:28                                                                                                     ` Abdellatif El Khlifi
  2023-06-16 15:28                                                                                                     ` [PATCH v13 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                                                                                       ` (3 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-06-16 15:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, nd, sjg, u-boot,
	achin.gupta, jens.wiklander, xueliang.zhong, Drew.Reed,
	Heinrich Schuchardt

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>
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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove reparenting by making the emulator parent of the FF-A device in the DT
* add invoke_ffa_fn()
* address nits

v11:

* rename ffa_try_discovery() to sandbox_ffa_discover()
* rename sandbox_ffa_query_core_state() to sandbox_query_ffa_emul_state()
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device

v10:

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

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

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

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

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

v1: introduce the sandbox driver

 MAINTAINERS                                   |   3 +-
 arch/sandbox/dts/sandbox.dtsi                 |   9 +
 arch/sandbox/dts/test.dts                     |   8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |  72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        | 121 +++
 configs/sandbox64_defconfig                   |   1 +
 configs/sandbox_defconfig                     |   1 +
 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, 1081 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 0d960731cf..dcdb0e9362 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..96b5404991 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1820,6 +1820,14 @@
 	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..72ea3d21ab 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -260,3 +260,4 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 1ec44d5b33..8269bec879 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -344,3 +344,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 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


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v13 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA
  2023-06-16 15:28                                                                                                   ` [PATCH v13 " Abdellatif El Khlifi
                                                                                                                       ` (5 preceding siblings ...)
  2023-06-16 15:28                                                                                                     ` [PATCH v13 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
@ 2023-06-16 15:28                                                                                                     ` Abdellatif El Khlifi
  2023-06-16 15:28                                                                                                     ` [PATCH v13 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                                                                                       ` (2 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-06-16 15:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, nd, sjg, u-boot,
	achin.gupta, jens.wiklander, xueliang.zhong, Drew.Reed,
	Heinrich Schuchardt

Add functional test cases for the FF-A support

These tests rely on the FF-A sandbox emulator and FF-A
sandbox driver which help in inspecting the FF-A communication.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove use of dscvry_info
* drop use of calloc when querying SPs
* address nits

v11:

* drop unmapping test (taken care of by the DM when removing the device)
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT
* address nits

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

v8:

  * update partition_info_get() second argument to be an SP count
  * pass NULL device pointer to the FF-A bus discovery and operations

v7: set the tests to use 64-bit direct messaging

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

v1: introduce sandbox tests

 MAINTAINERS            |   1 +
 doc/arch/arm64.ffa.rst |   1 +
 test/dm/Makefile       |   3 +-
 test/dm/ffa.c          | 261 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 265 insertions(+), 1 deletion(-)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index dcdb0e9362..8b32e66fa9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index b7c754fa3d..325fb80346 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -37,6 +37,7 @@ The U-Boot FF-A support provides the following parts:
   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.
+- Sandbox FF-A test cases.
 
 FF-A and SMC specifications
 -------------------------------------------
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 3799b1ae8f..7ed00733c1 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
-# Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -92,6 +92,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..6912666bb4
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <console.h>
+#include <dm.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <asm/sandbox_arm_ffa_priv.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Functional tests for the UCLASS_FFA */
+
+static int check_fwk_version(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	struct ffa_sandbox_data func_data;
+	u32 fwk_version = 0;
+
+	func_data.data0 = &fwk_version;
+	func_data.data0_size = sizeof(fwk_version);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_VERSION, &func_data));
+	ut_asserteq(uc_priv->fwk_version, fwk_version);
+
+	return 0;
+}
+
+static int check_endpoint_id(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_asserteq(0, uc_priv->id);
+
+	return 0;
+}
+
+static int check_rxtxbuf(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assertnonnull(uc_priv->pair.rxbuf);
+	ut_assertnonnull(uc_priv->pair.txbuf);
+
+	return 0;
+}
+
+static int check_features(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assert(uc_priv->pair.rxtx_min_pages == RXTX_4K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_16K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_64K);
+
+	return 0;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+		ut_asserteq(1, rxbuf_mapped);
+		break;
+	case FFA_RXTX_UNMAP:
+		ut_asserteq(0, rxbuf_mapped);
+		break;
+	default:
+		ut_assert(false);
+	}
+
+	return 0;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	ut_asserteq(0, rxbuf_owned);
+
+	return 0;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg;
+	u8 cnt;
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]);
+
+	return 0;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct unit_test_state *uts)
+{
+	struct ffa_partition_desc *descs;
+	u32 count, i, j, valid_sps = 0;
+	struct udevice *dev;
+	struct ffa_sandbox_data func_data;
+	struct ffa_partitions *partitions;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get from the driver the count and information of the SPs matching the UUID */
+	ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, &descs));
+
+	/* Make sure the count is correct */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+
+	/* SPs found , verify the partitions information */
+
+	func_data.data0 = &partitions;
+	func_data.data0_size = sizeof(struct ffa_partitions *);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_PARTITION_INFO_GET, &func_data));
+
+	for (i = 0; i < count ; i++) {
+		for (j = 0;
+		     j < partitions->count;
+		     j++) {
+			if (descs[i].info.id ==
+			   partitions->descs[j].info.id) {
+				valid_sps++;
+				ut_asserteq_mem(&descs[i],
+						&partitions->descs[j],
+						sizeof(struct ffa_partition_desc));
+				/* Send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(descs[i].info.id, uts);
+			}
+		}
+	}
+
+	/* Verify expected partitions found in the emulated secure world */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, valid_sps);
+
+	return 0;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	struct ffa_sandbox_data func_data;
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	struct udevice *dev;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Test FFA_VERSION */
+	check_fwk_version(uc_priv, uts);
+
+	/* Test FFA_ID_GET */
+	check_endpoint_id(uc_priv, uts);
+
+	/* Test FFA_FEATURES */
+	check_features(uc_priv, uts);
+
+	/*  Test RX/TX buffers */
+	check_rxtxbuf(uc_priv, uts);
+
+	/* Test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	sandbox_query_ffa_emul_state(FFA_RXTX_MAP, &func_data);
+	check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc1_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data);
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc2_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data));
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg;
+	int ret;
+	u32 count;
+	u16 part_id = 0;
+	struct udevice *dev;
+	struct ffa_partition_desc *descs = NULL;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Query partitions count using  invalid arguments */
+	ret = ffa_partition_info_get(dev, NULL, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, NULL);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID  string */
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid_str, &count, &descs);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, &descs);
+	ut_asserteq(0, count);
+
+	/* Query partitions data using a valid UUID */
+	count = 0;
+	ut_assertok(ffa_partition_info_get(dev, valid_svc_uuid, &count, &descs));
+	/* Make sure partitions are detected */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+	ut_assertnonnull(descs);
+
+	/* Send data to an invalid partition */
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Send data to a valid partition */
+	part_id = uc_priv->partitions.descs[0].info.id;
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v13 08/10] arm_ffa: introduce armffa command Sandbox test
  2023-06-16 15:28                                                                                                   ` [PATCH v13 " Abdellatif El Khlifi
                                                                                                                       ` (6 preceding siblings ...)
  2023-06-16 15:28                                                                                                     ` [PATCH v13 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-06-16 15:28                                                                                                     ` Abdellatif El Khlifi
  2023-06-16 15:28                                                                                                     ` [PATCH v13 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
  2023-06-16 15:28                                                                                                     ` [PATCH v13 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-06-16 15:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, nd, sjg, u-boot,
	achin.gupta, jens.wiklander, xueliang.zhong, Drew.Reed

Add Sandbox test for the armffa command

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
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>

---

Changelog:
===============

v12:

* address nits

v10:

* replace CMD_RET_SUCCESS with 0
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT

v9: align the test with FF-A discovery through DM

v4: drop use of helper APIs

v1: introduce armffa command sandbox test

 MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 8b32e66fa9..1c2d1fcf22 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 055adc65a2..1d1dbb4fbc 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -23,6 +24,7 @@ obj-$(CONFIG_CMD_SEAMA) += seama.o
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_CMD_READ) += rw.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o
 endif
 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
 obj-$(CONFIG_CMD_WGET) += wget.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..9a44a397e8
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * 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 <string.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	/* armffa ping <ID> */
+	ut_assertok(run_commandf("armffa ping 0x%x", SANDBOX_SP1_ID));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return 0;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v13 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-06-16 15:28                                                                                                   ` [PATCH v13 " Abdellatif El Khlifi
                                                                                                                       ` (7 preceding siblings ...)
  2023-06-16 15:28                                                                                                     ` [PATCH v13 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2023-06-16 15:28                                                                                                     ` Abdellatif El Khlifi
  2023-06-20 10:27                                                                                                       ` Simon Glass
  2023-06-21  6:21                                                                                                       ` Ilias Apalodimas
  2023-06-16 15:28                                                                                                     ` [PATCH v13 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  9 siblings, 2 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-06-16 15:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, nd, sjg, u-boot,
	achin.gupta, jens.wiklander, xueliang.zhong, Drew.Reed,
	Gowtham Suresh Kumar

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

MM communication protocol supports FF-A 64-bit direct messaging.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>

---

Changelog:
===============

v13:

* remove FF-A and Optee ifdefs

v12:

* drop use of calloc when querying SPs
* address nits

v11:

* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* addressing nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* addressing nits

v9: align how FF-A is used with FF-A discovery through DM

v8:

* isolate the compilation choices between FF-A and OP-TEE
* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make mm_sp_svc_uuid static
* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
* improve use of unmap_sysmem() in ffa_mm_communicate()

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

 include/mm_communication.h        |  13 ++
 lib/efi_loader/Kconfig            |  16 +-
 lib/efi_loader/efi_variable_tee.c | 260 +++++++++++++++++++++++++++++-
 3 files changed, 282 insertions(+), 7 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..f17847583b 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,9 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *    Authors:
+ *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +16,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
@@ -248,4 +254,11 @@ struct smm_variable_var_check_property {
 	u16                       name[];
 };
 
+/* supported MM transports */
+enum mm_comms_select {
+	MM_COMMS_UNDEFINED,
+	MM_COMMS_FFA,
+	MM_COMMS_OPTEE
+};
+
 #endif /* _MM_COMMUNICATION_H_ */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c5835e6ef6..cb26e110fd 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,25 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	select ARM_FFA_TRANSPORT
+	select TEE
+	select OPTEE
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..b4d1b979b7 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,17 +4,45 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  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 <cpu_func.h>
+#include <dm.h>
 #include <efi.h>
 #include <efi_api.h>
 #include <efi_loader.h>
 #include <efi_variable.h>
-#include <tee.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <mm_communication.h>
+#include <tee.h>
+
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_SIZE 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_OFFSET
+#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_OFFSET 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_ADDR 0
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
 
+static const char *mm_sp_svc_uuid = MM_SP_UUID;
+static u16 mm_sp_id;
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -145,16 +173,226 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 }
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notify the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret = -1;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
+		return ret;
+	}
+
+	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
+
+	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
+	if (ret)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	if (sp_event_ret == MM_SUCCESS)
+		return 0;
+
+	/* Failure to notify the MM SP */
+
+	return -EACCES;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
+		return ret;
+	}
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, &descs);
+	if (ret) {
+		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
+		return ret;
+	}
+
+	/* MM SPs found , use the first one */
+
+	mm_sp_id = descs[0].info.id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	return 0;
+}
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	efi_status_t efi_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()) {
+		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+
+	switch (ffa_ret) {
+	case 0: {
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		efi_ret = EFI_SUCCESS;
+		break;
+	}
+	case -EINVAL:
+		efi_ret = EFI_DEVICE_ERROR;
+		break;
+	case -EPERM:
+		efi_ret = EFI_INVALID_PARAMETER;
+		break;
+	case -EACCES:
+		efi_ret = EFI_ACCESS_DENIED;
+		break;
+	case -EBUSY:
+		efi_ret = EFI_OUT_OF_RESOURCES;
+		break;
+	default:
+		efi_ret = EFI_ACCESS_DENIED;
+	}
+
+	unmap_sysmem(virt_shared_buf);
+	return efi_ret;
+}
+
+/**
+ * get_mm_comms() - detect the available MM transport
+ *
+ * Make sure the FF-A bus is probed successfully
+ * which means FF-A communication with secure world works and ready
+ * for use.
+ *
+ * If FF-A bus is not ready, use OPTEE comms.
+ *
+ * Return:
+ *
+ * MM_COMMS_FFA or MM_COMMS_OPTEE
+ */
+static enum mm_comms_select get_mm_comms(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, trying Optee comms\n");
+		return MM_COMMS_OPTEE;
+	}
+
+	return MM_COMMS_FFA;
+}
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 {
 	efi_status_t ret;
+	enum mm_comms_select mm_comms;
 	struct efi_mm_communicate_header *mm_hdr;
 	struct smm_variable_communicate_header *var_hdr;
 
@@ -162,7 +400,12 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+	mm_comms = get_mm_comms();
+	if (mm_comms == MM_COMMS_FFA)
+		ret = ffa_mm_communicate(comm_buf, dsize);
+	else
+		ret = optee_mm_communicate(comm_buf, dsize);
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -232,6 +475,7 @@ static u8 *setup_mm_hdr(void **dptr, efi_uintn_t payload_size,
  */
 efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
 {
+	enum mm_comms_select mm_comms;
 	struct smm_variable_payload_size *var_payload = NULL;
 	efi_uintn_t payload_size;
 	u8 *comm_buf = NULL;
@@ -258,6 +502,12 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
 		goto out;
 	}
 	*size = var_payload->size;
+
+	mm_comms = get_mm_comms();
+	if (mm_comms == MM_COMMS_FFA && *size > FFA_SHARED_MM_BUFFER_SIZE)
+		*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
+			MM_VARIABLE_COMMUNICATE_SIZE;
+
 	/*
 	 * There seems to be a bug in EDK2 miscalculating the boundaries and
 	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
@@ -697,7 +947,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v13 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2023-06-16 15:28                                                                                                   ` [PATCH v13 " Abdellatif El Khlifi
                                                                                                                       ` (8 preceding siblings ...)
  2023-06-16 15:28                                                                                                     ` [PATCH v13 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-06-16 15:28                                                                                                     ` Abdellatif El Khlifi
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-06-16 15:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, nd, sjg, u-boot,
	achin.gupta, jens.wiklander, xueliang.zhong, Drew.Reed

turn on EFI MM communication

On corstone1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

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>

---

Changelog:
===============

v13:

* remove FF-A config in the defconfig
   (because it's enabled automatically by CONFIG_EFI_MM_COMM_TEE)

v9:

* update copyright string

v8:

* drop OP-TEE configs from Corstone-1000 defconfig

v7:

* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
  FFA_SHARED_MM_BUFFER_OFFSET
* update FFA_SHARED_MM_BUFFER_ADDR value

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

 configs/corstone1000_defconfig |  1 +
 include/configs/corstone1000.h | 15 +++++++++++++--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index 2d391048cd..e1f63237c4 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -53,3 +53,4 @@ CONFIG_DM_SERIAL=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760=y
 CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
index 3347c11792..4ef1f05e40 100644
--- a/include/configs/corstone1000.h
+++ b/include/configs/corstone1000.h
@@ -1,9 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * (C) Copyright 2022 ARM Limited
  * (C) Copyright 2022 Linaro
  * Rui Miguel Silva <rui.silva@linaro.org>
- * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  *
  * Configuration for Corstone1000. Parts were derived from other ARM
  * configurations.
@@ -14,6 +16,15 @@
 
 #include <linux/sizes.h>
 
+#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
+
+/*
+ * shared buffer physical address used for communication between
+ * u-boot and the MM SP
+ */
+#define FFA_SHARED_MM_BUFFER_ADDR	0x02000000UL
+#define FFA_SHARED_MM_BUFFER_OFFSET	0
+
 #define V2M_BASE		0x80000000
 
 #define CFG_PL011_CLOCK	50000000
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-06-16 15:28                                                                                                     ` [PATCH v13 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-06-20 10:27                                                                                                       ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-06-20 10:27 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: trini, ilias.apalodimas, nd, u-boot, achin.gupta, jens.wiklander,
	xueliang.zhong, Drew.Reed

On Fri, 16 Jun 2023 at 16:28, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> provide a test case
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Cc: Simon Glass <sjg@chromium.org>
>
> ---
>
> Changelog:
> ===============
>
> v11:
>
> * use ut_asserteq_mem()
>
>  MAINTAINERS       |  5 +++++
>  test/lib/Makefile |  1 +
>  test/lib/uuid.c   | 41 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 47 insertions(+)
>  create mode 100644 test/lib/uuid.c
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 04/10] arm_ffa: introduce Arm FF-A support
  2023-06-16 15:28                                                                                                     ` [PATCH v13 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-06-20 10:27                                                                                                       ` Simon Glass
  2023-06-30 12:49                                                                                                         ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-06-20 10:27 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: trini, ilias.apalodimas, nd, u-boot, achin.gupta, jens.wiklander,
	xueliang.zhong, Drew.Reed, Heinrich Schuchardt

On Fri, 16 Jun 2023 at 16:28, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0
>
> The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World leveraging TrustZone
> technology.
>
> This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> querying the FF-A framework from the secure world.
>
> The driver uses SMC32 calling convention which means using the first
> 32-bit data of the Xn registers.
>
> All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
> which has 64-bit version supported.
>
> Both 32-bit and 64-bit direct messaging are supported which allows both
> 32-bit and 64-bit clients to use the FF-A bus.
>
> FF-A is a discoverable bus and similar to architecture features.
> FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> by the PSCI driver.
>
> Clients are able to probe then use the FF-A bus by calling the DM class
> searching APIs (e.g: uclass_first_device).
>
> The Secure World is considered as one entity to communicate with
> using the FF-A bus. FF-A communication is handled by one device and
> one instance (the bus). This FF-A driver takes care of all the
> interactions between Normal world and Secure World.
>
> The driver exports its operations to be used by upper layers.
>
> Exported operations:
>
> - ffa_partition_info_get
> - ffa_sync_send_receive
> - ffa_rxtx_unmap
>
> 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 please refer to the driver documentation [2].
>
> [1]: https://developer.arm.com/documentation/den0077/latest/
> [2]: doc/arch/arm64.ffa.rst
>
> 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>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
>
> ---
>
> Changelog:
> ===============
>
> v13:
>
> * doc minor change: specify in the readme that the user
>    should call ffa_rxtx_unmap() driver operation to unmap
>    the RX/TX buffers on demand.
>
> v12:
>
> * remove dscvry_info
> * replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
>    (user drivers can override it)
> * improve FFA_PARTITION_INFO_GET implementation
>    (clients no longer need to calloc a buffer)
> * address nits
>
> v11:
>
> * move ffa_try_discovery() from the uclass to the Arm FF-A driver
> * rename ffa_try_discovery() to arm_ffa_discover()
> * pass dev as an argument of arm_ffa_discover()
> * add arm_ prefix to the Arm FF-A driver functions
> * add emul field in struct ffa_discovery_info
> * address nits
>
> v10:
>
> * provide the driver operations through the Uclass
> * move the generic FF-A methods to the Uclass
> * keep Arm specific methods in the Arm driver (arm-ffa.c)
> * rename core.c to arm-ffa.c
> * address nits
>
> v9:
>
> * integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
>
> v8:
>
> * make ffa_get_partitions_info() second argument to be an SP count in both
>   modes
> * update ffa_bus_prvdata_get() to return a pointer rather than a pointer
>   address
> * remove packing from ffa_partition_info and ffa_send_direct_data structures
> * pass the FF-A bus device to the bus operations
>
> v7:
>
> * add support for 32-bit direct messaging
> * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> * improve the declaration of error handling mapping
> * stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported
>
> v6:
>
> * drop use of EFI runtime support (We decided with Linaro to add this later)
> * drop discovery from initcalls (discovery will be on demand by FF-A users)
> * set the alignment of the RX/TX buffers to the larger translation granule size
> * move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
> * update the documentation and move it to doc/arch/arm64.ffa.rst
>
> v4:
>
> * add doc/README.ffa.drv
> * moving the FF-A driver work to drivers/firmware/arm-ffa
> * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
>   #if defined by #if CONFIG_IS_ENABLED
> * improving error handling by mapping the FF-A errors to standard errors
>   and logs
> * replacing panics with an error log and returning an error code
> * improving features discovery in FFA_FEATURES by introducing
>   rxtx_min_pages private data field
> * add ffa_remove and ffa_unbind functions
> * improve how the driver behaves when bus discovery is done more than
>   once
>
> v3:
>
> * align the interfaces of the U-Boot FF-A driver with those in the linux
>   FF-A driver
> * remove the FF-A helper layer
> * make the U-Boot FF-A driver independent from EFI
> * provide an optional config that enables copying the driver data to EFI
>   runtime section at ExitBootServices service
> * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
>
> v2:
>
> * make FF-A bus discoverable using device_{bind, probe} APIs
> * remove device tree support
>
> v1:
>
> * introduce FF-A bus driver with device tree support
>
>  MAINTAINERS                                   |    8 +
>  doc/arch/arm64.ffa.rst                        |  238 ++++
>  doc/arch/index.rst                            |    1 +
>  drivers/Makefile                              |    1 +
>  drivers/firmware/Kconfig                      |    1 +
>  drivers/firmware/arm-ffa/Kconfig              |   36 +
>  drivers/firmware/arm-ffa/Makefile             |    8 +
>  drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
>  drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
>  .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |   14 +
>  include/arm_ffa.h                             |  213 ++++
>  include/arm_ffa_priv.h                        |  246 ++++
>  include/dm/uclass-id.h                        |    6 +
>  13 files changed, 1941 insertions(+)
>  create mode 100644 doc/arch/arm64.ffa.rst
>  create mode 100644 drivers/firmware/arm-ffa/Kconfig
>  create mode 100644 drivers/firmware/arm-ffa/Makefile
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
>  create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 05/10] arm_ffa: introduce armffa command
  2023-06-16 15:28                                                                                                     ` [PATCH v13 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-06-20 10:27                                                                                                       ` Simon Glass
  2023-06-20 14:25                                                                                                       ` Ilias Apalodimas
  1 sibling, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-06-20 10:27 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: trini, ilias.apalodimas, nd, u-boot, achin.gupta, jens.wiklander,
	xueliang.zhong, Drew.Reed, Heinrich Schuchardt

On Fri, 16 Jun 2023 at 16:28, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Provide armffa command showcasing the use of the U-Boot FF-A support
>
> armffa is a command showcasing how to invoke FF-A operations.
> This provides a guidance to the client developers on how to
> call the FF-A bus interfaces. The command also allows to gather secure
> partitions information and ping these  partitions. The command is also
> helpful in testing the communication with secure partitions.
>
> For more details please refer to the command documentation [1].
>
> [1]: doc/usage/cmd/armffa.rst
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 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>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
>
> ---
>
> Changelog:
> ===============
>
> v12:
>
> * add subcommands argument checks
> * usage documentation: update command return codes
> * remove calloc when querying SPs
> * address nits
>
> v11:
>
> * use U_BOOT_CMD_WITH_SUBCMDS
> * address nits
>
> v10:
>
> * use the FF-A driver Uclass operations
> * use uclass_first_device()
> * address nits
>
> v9:
>
> * remove manual FF-A discovery and use DM
> * use DM class APIs to probe and interact with the FF-A bus
> * add doc/usage/cmd/armffa.rst
>
> v8:
>
> * update partition_info_get() second argument to be an SP count
> * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7:
>
> * adapt do_ffa_dev_list() following the recent update on
>   uclass_first_device/uclass_next_device functions (they return void now)
> * set armffa command to use 64-bit direct messaging
>
> v4:
>
> * remove pattern data in do_ffa_msg_send_direct_req
>
> v3:
>
> * use the new driver interfaces (partition_info_get, sync_send_receive)
>   in armffa command
>
> v2:
>
> * replace use of ffa_helper_init_device function by
>  ffa_helper_bus_discover
>
> v1:
>
> * introduce armffa command
>
>  MAINTAINERS                      |   2 +
>  cmd/Kconfig                      |  10 ++
>  cmd/Makefile                     |   1 +
>  cmd/armffa.c                     | 196 +++++++++++++++++++++++++++++++
>  doc/arch/arm64.ffa.rst           |   7 ++
>  doc/usage/cmd/armffa.rst         |  93 +++++++++++++++
>  doc/usage/index.rst              |   1 +
>  drivers/firmware/arm-ffa/Kconfig |   1 +
>  8 files changed, 311 insertions(+)
>  create mode 100644 cmd/armffa.c
>  create mode 100644 doc/usage/cmd/armffa.rst
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-06-16 15:28                                                                                                     ` [PATCH v13 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-06-20 10:27                                                                                                       ` Simon Glass
  2023-06-21  6:21                                                                                                       ` Ilias Apalodimas
  1 sibling, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-06-20 10:27 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: trini, ilias.apalodimas, nd, u-boot, achin.gupta, jens.wiklander,
	xueliang.zhong, Drew.Reed, Gowtham Suresh Kumar

On Fri, 16 Jun 2023 at 16:28, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Add MM communication support using FF-A transport
>
> This feature allows accessing MM partitions services through
> EFI MM communication protocol. MM partitions such as StandAlonneMM
> or smm-gateway secure partitions which reside in secure world.
>
> An MM shared buffer and a door bell event are used to exchange
> the data.
>
> The data is used by EFI services such as GetVariable()/SetVariable()
> and copied from the communication buffer to the MM shared buffer.
>
> The secure partition is notified about availability of data in the
> MM shared buffer by an FF-A message (door bell).
>
> On such event, MM SP can read the data and updates the MM shared
> buffer with the response data.
>
> The response data is copied back to the communication buffer and
> consumed by the EFI subsystem.
>
> MM communication protocol supports FF-A 64-bit direct messaging.
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>
>
> ---
>
> Changelog:
> ===============
>
> v13:
>
> * remove FF-A and Optee ifdefs
>
> v12:
>
> * drop use of calloc when querying SPs
> * address nits
>
> v11:
>
> * rename select_ffa_mm_comms() to select_mm_comms()
> * improve the logic of MM transport selection in mm_communicate()
> * addressing nits
>
> v10:
>
> * use the FF-A driver Uclass operations
> * use uclass_first_device()
> * addressing nits
>
> v9: align how FF-A is used with FF-A discovery through DM
>
> v8:
>
> * isolate the compilation choices between FF-A and OP-TEE
> * update partition_info_get() second argument to be an SP count
> * pass NULL device pointer to the FF-A bus discovery and operations
>
> v7:
>
> * set the MM door bell event to use 64-bit direct messaging
> * issue a compile time error when one of these macros are not found :
>   FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
> * make mm_sp_svc_uuid static
> * replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
> * improve use of unmap_sysmem() in ffa_mm_communicate()
>
> v6:
>
> * add FF-A runtime discovery at MM communication level
> * drop EFI runtime support for FF-A MM communication
> * revert the changes in include/mm_communication.h for
>   efi_mm_communicate_header and smm_variable_access structures
>
> v4:
>
> * use the new FF-A driver interfaces
> * discover MM partitions at runtime
> * copy FF-A driver private data to EFI runtime section at
>   ExitBootServices()
> * drop use of FFA_ERR_STAT_SUCCESS error code
> * replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
>   in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
> * revert the error log in mm_communicate() in case of failure
> * remove packed attribute from efi_mm_communicate_header and
>   smm_variable_communicate_header
>
> v2:
>
> * set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings
>
> v1:
>
> * introduce FF-A MM communication
>
>  include/mm_communication.h        |  13 ++
>  lib/efi_loader/Kconfig            |  16 +-
>  lib/efi_loader/efi_variable_tee.c | 260 +++++++++++++++++++++++++++++-
>  3 files changed, 282 insertions(+), 7 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-06-16 15:28                                                                                                     ` [PATCH v13 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-06-20 14:05                                                                                                       ` Ilias Apalodimas
  2023-07-03  9:47                                                                                                         ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-06-20 14:05 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: trini, nd, sjg, u-boot, achin.gupta, jens.wiklander,
	xueliang.zhong, Drew.Reed

Hi Abdellatif,

On Fri, 16 Jun 2023 at 18:28, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> add support for x0-x17 registers used by the SMC calls
>
> In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
> Results are returned in x0-x17.
>
> This work is inspired from the following kernel commit:
>
> arm64: smccc: Add support for SMCCCv1.2 extended input/output registers
>
> [1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

I did review this one in the past, any reason why that is missing?
Did the file change?

Thanks
/Ilias
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
>
> ---
>
> Changelog:
> ===============
>
> v9:
>
> * update the copyright string
>
> v7:
>
> * improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS
>
> v4:
>
> * rename the commit title and improve description
>   new commit title: the current
>
> v3:
>
> * port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
>   commit title:
>       arm64: smccc: add Xn registers support used by SMC calls
>
>  arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
>  arch/arm/lib/asm-offsets.c      | 16 +++++++++
>  include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
>  3 files changed, 117 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
> index dc92b28777..93f66d3366 100644
> --- a/arch/arm/cpu/armv8/smccc-call.S
> +++ b/arch/arm/cpu/armv8/smccc-call.S
> @@ -1,7 +1,11 @@
>  /* SPDX-License-Identifier: GPL-2.0 */
>  /*
>   * Copyright (c) 2015, Linaro Limited
> - */
> + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *
> + * Authors:
> + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +*/
>  #include <linux/linkage.h>
>  #include <linux/arm-smccc.h>
>  #include <generated/asm-offsets.h>
> @@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc)
>  ENTRY(__arm_smccc_hvc)
>         SMCCC   hvc
>  ENDPROC(__arm_smccc_hvc)
> +
> +#ifdef CONFIG_ARM64
> +
> +       .macro SMCCC_1_2 instr
> +       /* Save `res` and free a GPR that won't be clobbered */
> +       stp     x1, x19, [sp, #-16]!
> +
> +       /* Ensure `args` won't be clobbered while loading regs in next step */
> +       mov     x19, x0
> +
> +       /* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
> +       ldp     x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
> +       ldp     x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
> +       ldp     x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
> +       ldp     x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
> +       ldp     x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
> +       ldp     x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
> +       ldp     x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
> +       ldp     x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
> +       ldp     x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
> +
> +       \instr #0
> +
> +       /* Load the `res` from the stack */
> +       ldr     x19, [sp]
> +
> +       /* Store the registers x0 - x17 into the result structure */
> +       stp     x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
> +       stp     x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
> +       stp     x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
> +       stp     x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
> +       stp     x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
> +       stp     x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
> +       stp     x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
> +       stp     x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
> +       stp     x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
> +
> +       /* Restore original x19 */
> +       ldp     xzr, x19, [sp], #16
> +       ret
> +       .endm
> +
> +/*
> + * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
> + *                       struct arm_smccc_1_2_regs *res);
> + */
> +ENTRY(arm_smccc_1_2_smc)
> +       SMCCC_1_2 smc
> +ENDPROC(arm_smccc_1_2_smc)
> +
> +#endif
> diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
> index 6de0ce9152..181a8ac4c2 100644
> --- a/arch/arm/lib/asm-offsets.c
> +++ b/arch/arm/lib/asm-offsets.c
> @@ -9,6 +9,11 @@
>   * generate asm statements containing #defines,
>   * compile this file to assembler, and then extract the
>   * #defines from the assembly-language output.
> + *
> + * 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>
> @@ -90,6 +95,17 @@ int main(void)
>         DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
>         DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
>         DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
> +#ifdef CONFIG_ARM64
> +       DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,      offsetof(struct arm_smccc_1_2_regs, a0));
> +       DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,      offsetof(struct arm_smccc_1_2_regs, a2));
> +       DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,      offsetof(struct arm_smccc_1_2_regs, a4));
> +       DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,      offsetof(struct arm_smccc_1_2_regs, a6));
> +       DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,      offsetof(struct arm_smccc_1_2_regs, a8));
> +       DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,     offsetof(struct arm_smccc_1_2_regs, a10));
> +       DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,     offsetof(struct arm_smccc_1_2_regs, a12));
> +       DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,     offsetof(struct arm_smccc_1_2_regs, a14));
> +       DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,     offsetof(struct arm_smccc_1_2_regs, a16));
> +#endif
>  #endif
>
>         return 0;
> diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
> index e1d09884a1..f44e9e8f93 100644
> --- a/include/linux/arm-smccc.h
> +++ b/include/linux/arm-smccc.h
> @@ -1,6 +1,10 @@
>  /* SPDX-License-Identifier: GPL-2.0 */
>  /*
>   * Copyright (c) 2015, Linaro Limited
> + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *
> + * Authors:
> + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  #ifndef __LINUX_ARM_SMCCC_H
>  #define __LINUX_ARM_SMCCC_H
> @@ -70,6 +74,47 @@ struct arm_smccc_res {
>         unsigned long a3;
>  };
>
> +#ifdef CONFIG_ARM64
> +/**
> + * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
> + * @a0-a17 argument values from registers 0 to 17
> + */
> +struct arm_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;
> +};
> +
> +/**
> + * arm_smccc_1_2_smc() - make SMC calls
> + * @args: arguments passed via struct arm_smccc_1_2_regs
> + * @res: result values via struct arm_smccc_1_2_regs
> + *
> + * This function is used to make SMC calls following SMC Calling Convention
> + * v1.2 or above. The content of the supplied param are copied from the
> + * structure to registers prior to the SMC instruction. The return values
> + * are updated with the content from registers on return from the SMC
> + * instruction.
> + */
> +asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
> +                                 struct arm_smccc_1_2_regs *res);
> +#endif
> +
>  /**
>   * struct arm_smccc_quirk - Contains quirk information
>   * @id: quirk identification
> --
> 2.25.1
>

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 05/10] arm_ffa: introduce armffa command
  2023-06-16 15:28                                                                                                     ` [PATCH v13 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
  2023-06-20 10:27                                                                                                       ` Simon Glass
@ 2023-06-20 14:25                                                                                                       ` Ilias Apalodimas
  2023-07-03  9:55                                                                                                         ` Abdellatif El Khlifi
  1 sibling, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-06-20 14:25 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: trini, nd, sjg, u-boot, achin.gupta, jens.wiklander,
	xueliang.zhong, Drew.Reed, Heinrich Schuchardt

[...]

>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 43603522fd..0d960731cf 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -269,7 +269,9 @@ F:  configs/cortina_presidio-asic-pnand_defconfig
>  ARM FF-A
>  M:     Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>  S:     Maintained
> +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
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 365371fb51..86af7bcc9e 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -934,6 +934,16 @@ endmenu
>
>  menu "Device access commands"
>
> +config CMD_ARMFFA
> +       bool "Arm FF-A test command"
> +       depends on ARM_FFA_TRANSPORT
> +       help
> +         Provides a test command for the FF-A support
> +         supported options:
> +               - Listing the partition(s) info
> +               - Sending a data pattern to the specified partition
> +               - Displaying the arm_ffa device info
> +
>  config CMD_ARMFLASH
>         #depends on FLASH_CFI_DRIVER
>         bool "armflash"
> diff --git a/cmd/Makefile b/cmd/Makefile
> index 6c37521b4e..7d20a85a46 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -12,6 +12,7 @@ obj-y += panic.o
>  obj-y += version.o
>
>  # command
> +obj-$(CONFIG_CMD_ARMFFA) += armffa.o
>  obj-$(CONFIG_CMD_2048) += 2048.o
>  obj-$(CONFIG_CMD_ACPI) += acpi.o
>  obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
> diff --git a/cmd/armffa.c b/cmd/armffa.c
> new file mode 100644
> index 0000000000..fa268e9cb9
> --- /dev/null
> +++ b/cmd/armffa.c
> @@ -0,0 +1,196 @@
> +// 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 <command.h>
> +#include <dm.h>
> +#include <mapmem.h>
> +#include <stdlib.h>
> +#include <asm/io.h>
> +
> +/**
> + * ffa_get_dev() - Return the FF-A device
> + * @devp:      pointer to the FF-A device
> + *
> + * Search for the FF-A device.
> + *
> + * Return:
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_get_dev(struct udevice **devp)

Why isn't this static?  If it's used in another file we need to move
it to a library suitable file.

> +{
> +       int ret;
> +
> +       ret = uclass_first_device_err(UCLASS_FFA, devp);
> +       if (ret) {
> +               log_err("Cannot find FF-A bus device\n");
> +               return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +/**
> + * do_ffa_getpart() - implementation of the getpart subcommand
> + * @cmdtp:             Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * Query the secure partition information which the UUID is provided
> + * as an argument. The function uses the arm_ffa driver
> + * partition_info_get operation which implements FFA_PARTITION_INFO_GET
> + * ABI to retrieve the data. The input UUID string is expected to be in big
> + * endian format.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
> +                         char *const argv[])
> +{
> +       u32 count = 0;
> +       int ret;
> +       struct ffa_partition_desc *descs;
> +       u32 i;
> +       struct udevice *dev;
> +
> +       if (argc != 2) {
> +               log_err("Missing argument\n");
> +               return CMD_RET_USAGE;
> +       }
> +
> +       ret = ffa_get_dev(&dev);
> +       if (ret)
> +               return CMD_RET_FAILURE;
> +
> +       /* Ask the driver to fill the buffer with the SPs info */
> +
> +       ret = ffa_partition_info_get(dev, argv[1], &count, &descs);
> +       if (ret) {
> +               log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       /* SPs found , show the partition information */
> +       for (i = 0; i < count ; i++) {
> +               log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
> +                        descs[i].info.id,
> +                        descs[i].info.exec_ctxt,
> +                        descs[i].info.properties);
> +       }
> +
> +       return CMD_RET_SUCCESS;
> +}
> +
> +/**
> + * do_ffa_ping() - implementation of the ping subcommand
> + * @cmdtp:             Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * Send data to the secure partition which the ID is provided

s/which/ in which/

> + * as an argument. Use the arm_ffa driver sync_send_receive operation
> + * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       struct ffa_send_direct_data msg = {
> +                       .data0 = 0xaaaaaaaa,
> +                       .data1 = 0xbbbbbbbb,
> +                       .data2 = 0xcccccccc,
> +                       .data3 = 0xdddddddd,
> +                       .data4 = 0xeeeeeeee,
> +       };
> +       u16 part_id;
> +       int ret;
> +       struct udevice *dev;
> +
> +       if (argc != 2) {
> +               log_err("Missing argument\n");
> +               return CMD_RET_USAGE;
> +       }
> +
> +       errno = 0;
> +       part_id = strtoul(argv[1], NULL, 16);
> +
> +       if (errno) {

Is errno used in strtoul?
Does FF-A have any limits regarding the partition id? If yes, it would
be saner to check against that.

> +               log_err("Invalid partition ID\n");
> +               return CMD_RET_USAGE;
> +       }
> +
> +       ret = ffa_get_dev(&dev);
> +       if (ret)
> +               return CMD_RET_FAILURE;
> +
> +       ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
> +       if (!ret) {
> +               u8 cnt;
> +
> +               log_info("SP response:\n[LSB]\n");
> +               for (cnt = 0;
> +                    cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
> +                    cnt++)
> +                       log_info("%llx\n", ((u64 *)&msg)[cnt]);

I am not sure I understand why we print it like this.

> +               return CMD_RET_SUCCESS;
> +       }
> +
> +       log_err("Sending direct request error (%d)\n", ret);
> +       return CMD_RET_FAILURE;
> +}
> +
> +/**
> + *do_ffa_devlist() - implementation of the devlist subcommand
> + * @cmdtp: [in]                Command Table
> + * @flag:              flags
> + * @argc:              number of arguments
> + * @argv:              arguments
> + *
> + * Query the device belonging to the UCLASS_FFA
> + * class.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       struct udevice *dev;
> +       int ret;
> +
> +       ret = ffa_get_dev(&dev);
> +       if (ret)
> +               return CMD_RET_FAILURE;
> +
> +       log_info("device name %s, dev %p, driver name %s, ops %p\n",
> +                dev->name,
> +               (void *)map_to_sysmem(dev),
> +                dev->driver->name,
> +                (void *)map_to_sysmem(dev->driver->ops));

Isn't it more useful to print the physical address map_to_sysmem() retuns?

> +
> +       return CMD_RET_SUCCESS;
> +}
> +
>

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-06-16 15:28                                                                                                     ` [PATCH v13 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
  2023-06-20 10:27                                                                                                       ` Simon Glass
@ 2023-06-21  6:21                                                                                                       ` Ilias Apalodimas
  1 sibling, 0 replies; 478+ messages in thread
From: Ilias Apalodimas @ 2023-06-21  6:21 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: trini, nd, sjg, u-boot, achin.gupta, jens.wiklander,
	xueliang.zhong, Drew.Reed, Gowtham Suresh Kumar

Hi Abdellatif,

On Fri, Jun 16, 2023 at 04:28:16PM +0100, Abdellatif El Khlifi wrote:
> Add MM communication support using FF-A transport
>
> This feature allows accessing MM partitions services through
> EFI MM communication protocol. MM partitions such as StandAlonneMM
> or smm-gateway secure partitions which reside in secure world.
>
> An MM shared buffer and a door bell event are used to exchange
> the data.
>
> The data is used by EFI services such as GetVariable()/SetVariable()
> and copied from the communication buffer to the MM shared buffer.
>
> The secure partition is notified about availability of data in the
> MM shared buffer by an FF-A message (door bell).
>
> On such event, MM SP can read the data and updates the MM shared
> buffer with the response data.
>
> The response data is copied back to the communication buffer and
> consumed by the EFI subsystem.
>
> MM communication protocol supports FF-A 64-bit direct messaging.
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@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>
>
> ---
>
> Changelog:
> ===============
>
> v13:
>
> * remove FF-A and Optee ifdefs

Thanks this looks a lot saner now.  I got one last nit and I think this
patch is ready

> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_notify_mm_sp(void)
> +{
> +	struct ffa_send_direct_data msg = {0};
> +	int ret;
> +	int sp_event_ret = -1;
> +	struct udevice *dev;
> +
> +	ret = uclass_first_device_err(UCLASS_FFA, &dev);
> +	if (ret) {
> +		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
> +		return ret;
> +	}
> +
> +	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
> +
> +	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
> +	if (ret)
> +		return ret;
> +
> +	sp_event_ret = msg.data0; /* x3 */
> +
> +	if (sp_event_ret == MM_SUCCESS)
> +		return 0;
> +
> +	/* Failure to notify the MM SP */
> +
> +	return -EACCES;

Doesn't FFA and the SMM_GATEWAY have discrete returns results that would
make more sense?  Your other patches only define MM_SUCCESS but in
ffa_mm_communicate() you are trying to map ernnos to EFI return codes.
I think we should map errnos to ffa errors as well in a similar fashion.

You can look at optee_mm_communicate() which already does that.

> +}
> +
> +/**
> + * ffa_discover_mm_sp_id() - Query the MM partition ID
> + *
> +/**
> + * get_mm_comms() - detect the available MM transport
> + *
> + * Make sure the FF-A bus is probed successfully
> + * which means FF-A communication with secure world works and ready
> + * for use.
> + *
> + * If FF-A bus is not ready, use OPTEE comms.
> + *
> + * Return:
> + *
> + * MM_COMMS_FFA or MM_COMMS_OPTEE
> + */
> +static enum mm_comms_select get_mm_comms(void)
> +{
> +	struct udevice *dev;
> +	int ret;
> +
> +	ret = uclass_first_device_err(UCLASS_FFA, &dev);
> +	if (ret) {
> +		log_err("EFI: Cannot find FF-A bus device, trying Optee comms\n");
> +		return MM_COMMS_OPTEE;
> +	}
> +
> +	return MM_COMMS_FFA;
> +}
> +
> +/**
> + * mm_communicate() - Adjust the communication buffer to the MM SP and send
>   * it to OP-TEE
>   *
> - * @comm_buf:		locally allocted communcation buffer
> + * @comm_buf:		locally allocated communication buffer
>   * @dsize:		buffer size
> + *
> + * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
> + * The comm_buf format is the same for both partitions.
> + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> + * When using the u-boot FF-A  driver, any MM SP is supported.
> + *
>   * Return:		status code
>   */
>  static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  {
>  	efi_status_t ret;
> +	enum mm_comms_select mm_comms;
>  	struct efi_mm_communicate_header *mm_hdr;
>  	struct smm_variable_communicate_header *var_hdr;
>
> @@ -162,7 +400,12 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
>  	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
>
> -	ret = optee_mm_communicate(comm_buf, dsize);
> +	mm_comms = get_mm_comms();
> +	if (mm_comms == MM_COMMS_FFA)
> +		ret = ffa_mm_communicate(comm_buf, dsize);
> +	else
> +		ret = optee_mm_communicate(comm_buf, dsize);
> +
>  	if (ret != EFI_SUCCESS) {
>  		log_err("%s failed!\n", __func__);
>  		return ret;
> @@ -232,6 +475,7 @@ static u8 *setup_mm_hdr(void **dptr, efi_uintn_t payload_size,
>   */
>  efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
>  {
> +	enum mm_comms_select mm_comms;
>  	struct smm_variable_payload_size *var_payload = NULL;
>  	efi_uintn_t payload_size;
>  	u8 *comm_buf = NULL;
> @@ -258,6 +502,12 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size)
>  		goto out;
>  	}
>  	*size = var_payload->size;
> +
> +	mm_comms = get_mm_comms();
> +	if (mm_comms == MM_COMMS_FFA && *size > FFA_SHARED_MM_BUFFER_SIZE)
> +		*size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE	-
> +			MM_VARIABLE_COMMUNICATE_SIZE;
> +

Can you please move this check?  The check preceding this is generic -- it
tries to make sure there's space for at least a variable.  This is ffa
specific, so is there any reason ffa_mm_communicate() doesn't return the
corrected size?

>  	/*
>  	 * There seems to be a bug in EDK2 miscalculating the boundaries and
>  	 * size checks, so deduct 2 more bytes to fulfill this requirement. Fix
> @@ -697,7 +947,7 @@ void efi_variables_boot_exit_notify(void)
>  		ret = EFI_NOT_FOUND;
>
>  	if (ret != EFI_SUCCESS)
> -		log_err("Unable to notify StMM for ExitBootServices\n");
> +		log_err("Unable to notify the MM partition for ExitBootServices\n");
>  	free(comm_buf);
>
>  	/*
> --
> 2.25.1
>


Thanks
/Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 04/10] arm_ffa: introduce Arm FF-A support
  2023-06-20 10:27                                                                                                       ` Simon Glass
@ 2023-06-30 12:49                                                                                                         ` Abdellatif El Khlifi
  2023-07-02 15:44                                                                                                           ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-06-30 12:49 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, nd

Hi Simon,

On Tue, Jun 20, 2023 at 11:27:20AM +0100, Simon Glass wrote:
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0
> >
> > The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> > describes interfaces (ABIs) that standardize communication
> > between the Secure World and Normal World leveraging TrustZone
> > technology.
> >
> > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > querying the FF-A framework from the secure world.
> >
> > The driver uses SMC32 calling convention which means using the first
> > 32-bit data of the Xn registers.
> >
> > All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
> > which has 64-bit version supported.
> >
> > Both 32-bit and 64-bit direct messaging are supported which allows both
> > 32-bit and 64-bit clients to use the FF-A bus.
> >
> > FF-A is a discoverable bus and similar to architecture features.
> > FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> > by the PSCI driver.
> >
> > Clients are able to probe then use the FF-A bus by calling the DM class
> > searching APIs (e.g: uclass_first_device).
> >
> > The Secure World is considered as one entity to communicate with
> > using the FF-A bus. FF-A communication is handled by one device and
> > one instance (the bus). This FF-A driver takes care of all the
> > interactions between Normal world and Secure World.
> >
> > The driver exports its operations to be used by upper layers.
> >
> > Exported operations:
> >
> > - ffa_partition_info_get
> > - ffa_sync_send_receive
> > - ffa_rxtx_unmap
> >
> > 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 please refer to the driver documentation [2].
> >
> > [1]: https://developer.arm.com/documentation/den0077/latest/
> > [2]: doc/arch/arm64.ffa.rst
> >
> > 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>
> > Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
> >
> > ---
> >
> > Changelog:
> > ===============
> >
> > v13:
> >
> > * doc minor change: specify in the readme that the user
> >    should call ffa_rxtx_unmap() driver operation to unmap
> >    the RX/TX buffers on demand.

Are you happy with this commit please ? May I add a Reviewed-by ?

Cheers
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 04/10] arm_ffa: introduce Arm FF-A support
  2023-06-30 12:49                                                                                                         ` Abdellatif El Khlifi
@ 2023-07-02 15:44                                                                                                           ` Simon Glass
  2023-07-03  9:41                                                                                                             ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-07-02 15:44 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: u-boot, nd

Hi Abdellatif,

On Fri, 30 Jun 2023 at 13:49, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Hi Simon,
>
> On Tue, Jun 20, 2023 at 11:27:20AM +0100, Simon Glass wrote:
> > <abdellatif.elkhlifi@arm.com> wrote:
> > >
> > > Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0
> > >
> > > The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> > > describes interfaces (ABIs) that standardize communication
> > > between the Secure World and Normal World leveraging TrustZone
> > > technology.
> > >
> > > This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> > > on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> > > querying the FF-A framework from the secure world.
> > >
> > > The driver uses SMC32 calling convention which means using the first
> > > 32-bit data of the Xn registers.
> > >
> > > All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
> > > which has 64-bit version supported.
> > >
> > > Both 32-bit and 64-bit direct messaging are supported which allows both
> > > 32-bit and 64-bit clients to use the FF-A bus.
> > >
> > > FF-A is a discoverable bus and similar to architecture features.
> > > FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> > > by the PSCI driver.
> > >
> > > Clients are able to probe then use the FF-A bus by calling the DM class
> > > searching APIs (e.g: uclass_first_device).
> > >
> > > The Secure World is considered as one entity to communicate with
> > > using the FF-A bus. FF-A communication is handled by one device and
> > > one instance (the bus). This FF-A driver takes care of all the
> > > interactions between Normal world and Secure World.
> > >
> > > The driver exports its operations to be used by upper layers.
> > >
> > > Exported operations:
> > >
> > > - ffa_partition_info_get
> > > - ffa_sync_send_receive
> > > - ffa_rxtx_unmap
> > >
> > > 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 please refer to the driver documentation [2].
> > >
> > > [1]: https://developer.arm.com/documentation/den0077/latest/
> > > [2]: doc/arch/arm64.ffa.rst
> > >
> > > 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>
> > > Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
> > >
> > > ---
> > >
> > > Changelog:
> > > ===============
> > >
> > > v13:
> > >
> > > * doc minor change: specify in the readme that the user
> > >    should call ffa_rxtx_unmap() driver operation to unmap
> > >    the RX/TX buffers on demand.
>
> Are you happy with this commit please ? May I add a Reviewed-by ?

Sorry I think I did something wrong on the previous reply.

Reviewed-by: Simon Glass <sjg@chromium.org>

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 04/10] arm_ffa: introduce Arm FF-A support
  2023-07-02 15:44                                                                                                           ` Simon Glass
@ 2023-07-03  9:41                                                                                                             ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-03  9:41 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, nd

Hi Simon,

On Sun, Jul 02, 2023 at 04:44:41PM +0100, Simon Glass wrote:
> Hi Abdellatif,
>
...
> > > > Changelog:
> > > > ===============
> > > >
> > > > v13:
> > > >
> > > > * doc minor change: specify in the readme that the user
> > > >    should call ffa_rxtx_unmap() driver operation to unmap
> > > >    the RX/TX buffers on demand.
> >
> > Are you happy with this commit please ? May I add a Reviewed-by ?
> 
> Sorry I think I did something wrong on the previous reply.
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 

Thanks.

Are you happy with the Sandbox support commit too [1] ?

[1]: arm_ffa: introduce sandbox FF-A support

Cheers
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-06-20 14:05                                                                                                       ` Ilias Apalodimas
@ 2023-07-03  9:47                                                                                                         ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-03  9:47 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, nd

Hi Ilias,

On Tue, Jun 20, 2023 at 05:05:52PM +0300, Ilias Apalodimas wrote:
> Hi Abdellatif,
> 
> On Fri, 16 Jun 2023 at 18:28, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > add support for x0-x17 registers used by the SMC calls
> >
> > In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
> > Results are returned in x0-x17.
> >
> > This work is inspired from the following kernel commit:
> >
> > arm64: smccc: Add support for SMCCCv1.2 extended input/output registers
> >
> > [1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=
> 
> I did review this one in the past, any reason why that is missing?
> Did the file change?

Thanks, I was waiting for your confirmation. I'll add your Reviewed-by in v14.

Cheers

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 05/10] arm_ffa: introduce armffa command
  2023-06-20 14:25                                                                                                       ` Ilias Apalodimas
@ 2023-07-03  9:55                                                                                                         ` Abdellatif El Khlifi
  2023-07-03  9:59                                                                                                           ` Ilias Apalodimas
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-03  9:55 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: nd, u-boot

Hi Ilias,

On Tue, Jun 20, 2023 at 05:25:51PM +0300, Ilias Apalodimas wrote:
> [...]
> > +int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > +{
> > +       struct ffa_send_direct_data msg = {
> > +                       .data0 = 0xaaaaaaaa,
> > +                       .data1 = 0xbbbbbbbb,
> > +                       .data2 = 0xcccccccc,
> > +                       .data3 = 0xdddddddd,
> > +                       .data4 = 0xeeeeeeee,
> > +       };
> > +       u16 part_id;
> > +       int ret;
> > +       struct udevice *dev;
> > +
> > +       if (argc != 2) {
> > +               log_err("Missing argument\n");
> > +               return CMD_RET_USAGE;
> > +       }
> > +
> > +       errno = 0;
> > +       part_id = strtoul(argv[1], NULL, 16);
> > +
> > +       if (errno) {
> 
> Is errno used in strtoul?

Yes, please refer to [1].

[1]: https://man7.org/linux/man-pages/man3/strtoul.3.html

> Does FF-A have any limits regarding the partition id? If yes, it would
> be saner to check against that.

The only value that would be invalid is 0. I'll  add a check for that in v14.

> 
> > +               log_err("Invalid partition ID\n");
> > +               return CMD_RET_USAGE;
> > +       }
> > +
> > +       ret = ffa_get_dev(&dev);
> > +       if (ret)
> > +               return CMD_RET_FAILURE;
> > +
> > +       ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
> > +       if (!ret) {
> > +               u8 cnt;
> > +
> > +               log_info("SP response:\n[LSB]\n");
> > +               for (cnt = 0;
> > +                    cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
> > +                    cnt++)
> > +                       log_info("%llx\n", ((u64 *)&msg)[cnt]);
> 
> I am not sure I understand why we print it like this.

We would like to show the data received from secure world and in which order.

        example:
      
        corstone1000# armffa ping 0x8003
        SP response:
        [LSB]
        fffffffe
        0
        0
        0
        0

> 
> > +               return CMD_RET_SUCCESS;
> > +       }
> > +
> > +       log_err("Sending direct request error (%d)\n", ret);
> > +       return CMD_RET_FAILURE;
> > +}
> > +
> > +/**
> > + *do_ffa_devlist() - implementation of the devlist subcommand
> > + * @cmdtp: [in]                Command Table
> > + * @flag:              flags
> > + * @argc:              number of arguments
> > + * @argv:              arguments
> > + *
> > + * Query the device belonging to the UCLASS_FFA
> > + * class.
> > + *
> > + * Return:
> > + *
> > + * CMD_RET_SUCCESS: on success, otherwise failure
> > + */
> > +int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > +{
> > +       struct udevice *dev;
> > +       int ret;
> > +
> > +       ret = ffa_get_dev(&dev);
> > +       if (ret)
> > +               return CMD_RET_FAILURE;
> > +
> > +       log_info("device name %s, dev %p, driver name %s, ops %p\n",
> > +                dev->name,
> > +               (void *)map_to_sysmem(dev),
> > +                dev->driver->name,
> > +                (void *)map_to_sysmem(dev->driver->ops));
> 
> Isn't it more useful to print the physical address map_to_sysmem() retuns?

That's what map_to_sysmem() does, it returns a physical address and it's  shown in the log.

Cheers,
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 05/10] arm_ffa: introduce armffa command
  2023-07-03  9:55                                                                                                         ` Abdellatif El Khlifi
@ 2023-07-03  9:59                                                                                                           ` Ilias Apalodimas
  2023-07-03 12:08                                                                                                             ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-07-03  9:59 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: nd, u-boot

On Mon, 3 Jul 2023 at 12:55, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Hi Ilias,
>
> On Tue, Jun 20, 2023 at 05:25:51PM +0300, Ilias Apalodimas wrote:
> > [...]
> > > +int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > > +{
> > > +       struct ffa_send_direct_data msg = {
> > > +                       .data0 = 0xaaaaaaaa,
> > > +                       .data1 = 0xbbbbbbbb,
> > > +                       .data2 = 0xcccccccc,
> > > +                       .data3 = 0xdddddddd,
> > > +                       .data4 = 0xeeeeeeee,
> > > +       };
> > > +       u16 part_id;
> > > +       int ret;
> > > +       struct udevice *dev;
> > > +
> > > +       if (argc != 2) {
> > > +               log_err("Missing argument\n");
> > > +               return CMD_RET_USAGE;
> > > +       }
> > > +
> > > +       errno = 0;
> > > +       part_id = strtoul(argv[1], NULL, 16);
> > > +
> > > +       if (errno) {
> >
> > Is errno used in strtoul?
>
> Yes, please refer to [1].
>
> [1]: https://man7.org/linux/man-pages/man3/strtoul.3.html


that's what the libc version does.  Can you check the u-boot version?

>
> > Does FF-A have any limits regarding the partition id? If yes, it would
> > be saner to check against that.
>
> The only value that would be invalid is 0. I'll  add a check for that in v14.
>
> >
> > > +               log_err("Invalid partition ID\n");
> > > +               return CMD_RET_USAGE;
> > > +       }
> > > +
> > > +       ret = ffa_get_dev(&dev);
> > > +       if (ret)
> > > +               return CMD_RET_FAILURE;
> > > +
> > > +       ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
> > > +       if (!ret) {
> > > +               u8 cnt;
> > > +
> > > +               log_info("SP response:\n[LSB]\n");
> > > +               for (cnt = 0;
> > > +                    cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
> > > +                    cnt++)
> > > +                       log_info("%llx\n", ((u64 *)&msg)[cnt]);
> >
> > I am not sure I understand why we print it like this.
>
> We would like to show the data received from secure world and in which order.
>
>         example:
>
>         corstone1000# armffa ping 0x8003
>         SP response:
>         [LSB]
>         fffffffe
>         0
>         0
>         0
>         0
>
> >
> > > +               return CMD_RET_SUCCESS;
> > > +       }
> > > +
> > > +       log_err("Sending direct request error (%d)\n", ret);
> > > +       return CMD_RET_FAILURE;
> > > +}
> > > +
> > > +/**
> > > + *do_ffa_devlist() - implementation of the devlist subcommand
> > > + * @cmdtp: [in]                Command Table
> > > + * @flag:              flags
> > > + * @argc:              number of arguments
> > > + * @argv:              arguments
> > > + *
> > > + * Query the device belonging to the UCLASS_FFA
> > > + * class.
> > > + *
> > > + * Return:
> > > + *
> > > + * CMD_RET_SUCCESS: on success, otherwise failure
> > > + */
> > > +int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > > +{
> > > +       struct udevice *dev;
> > > +       int ret;
> > > +
> > > +       ret = ffa_get_dev(&dev);
> > > +       if (ret)
> > > +               return CMD_RET_FAILURE;
> > > +
> > > +       log_info("device name %s, dev %p, driver name %s, ops %p\n",
> > > +                dev->name,
> > > +               (void *)map_to_sysmem(dev),
> > > +                dev->driver->name,
> > > +                (void *)map_to_sysmem(dev->driver->ops));
> >
> > Isn't it more useful to print the physical address map_to_sysmem() retuns?
>
> That's what map_to_sysmem() does, it returns a physical address and it's  shown in the log.

I dont have access to u-boot source right, but why do you need all
these void * casts then?

Thanks
/Ilias
>
> Cheers,
> Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 05/10] arm_ffa: introduce armffa command
  2023-07-03  9:59                                                                                                           ` Ilias Apalodimas
@ 2023-07-03 12:08                                                                                                             ` Abdellatif El Khlifi
  2023-07-03 13:30                                                                                                               ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-03 12:08 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: nd, u-boot

Hi Ilias,

On Mon, Jul 03, 2023 at 12:59:58PM +0300, Ilias Apalodimas wrote:
> > > [...]
> > > > +int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > > > +{
> > > > +       struct ffa_send_direct_data msg = {
> > > > +                       .data0 = 0xaaaaaaaa,
> > > > +                       .data1 = 0xbbbbbbbb,
> > > > +                       .data2 = 0xcccccccc,
> > > > +                       .data3 = 0xdddddddd,
> > > > +                       .data4 = 0xeeeeeeee,
> > > > +       };
> > > > +       u16 part_id;
> > > > +       int ret;
> > > > +       struct udevice *dev;
> > > > +
> > > > +       if (argc != 2) {
> > > > +               log_err("Missing argument\n");
> > > > +               return CMD_RET_USAGE;
> > > > +       }
> > > > +
> > > > +       errno = 0;
> > > > +       part_id = strtoul(argv[1], NULL, 16);
> > > > +
> > > > +       if (errno) {
> > >
> > > Is errno used in strtoul?
> >
> > Yes, please refer to [1].
> >
> > [1]: https://man7.org/linux/man-pages/man3/strtoul.3.html
> 
> 
> that's what the libc version does.  Can you check the u-boot version?
> 

Short answer: errno not used in strtoul() an I'm gonna remove the errno check.

More details:

strtoul() is defined as simple_strtoul() in strto.c
errno variable is not set by simple_strtoul() or its callees.
errno.h is included by strto.c to access the error codes.

> > >
...
> > > > +int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > > > +{
> > > > +       struct udevice *dev;
> > > > +       int ret;
> > > > +
> > > > +       ret = ffa_get_dev(&dev);
> > > > +       if (ret)
> > > > +               return CMD_RET_FAILURE;
> > > > +
> > > > +       log_info("device name %s, dev %p, driver name %s, ops %p\n",
> > > > +                dev->name,
> > > > +               (void *)map_to_sysmem(dev),
> > > > +                dev->driver->name,
> > > > +                (void *)map_to_sysmem(dev->driver->ops));
> > >
> > > Isn't it more useful to print the physical address map_to_sysmem() retuns?
> >
> > That's what map_to_sysmem() does, it returns a physical address and it's  shown in the log.
> 
> I dont have access to u-boot source right, but why do you need all
> these void * casts then?

Because map_to_sysmem() returns an 'phys_addr_t' (aka 'long long unsigned int') . However, %p expects 'void *'.

Compilation warning:

cmd/armffa.c:181:18: warning: format ‘%p’ expects argument of type ‘void *’, but argument 3 has type ‘phys_addr_t’ {aka ‘long long unsigned int’} [8;
;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat=-Wformat=8;;]
  181 |         log_info("device name %s, dev %p, driver name %s, ops %p\n",
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  182 |                  dev->name,
  183 |                  map_to_sysmem(dev),
      |                  ~~~~~~~~~~~~~~~~~~
      |                  |
      |                  phys_addr_t {aka long long unsigned int}
      

Cheers,
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 05/10] arm_ffa: introduce armffa command
  2023-07-03 12:08                                                                                                             ` Abdellatif El Khlifi
@ 2023-07-03 13:30                                                                                                               ` Simon Glass
  2023-07-03 15:53                                                                                                                 ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-07-03 13:30 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: Ilias Apalodimas, nd, u-boot

Hi Abdellatif,

On Mon, 3 Jul 2023 at 13:09, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Hi Ilias,
>
> On Mon, Jul 03, 2023 at 12:59:58PM +0300, Ilias Apalodimas wrote:
> > > > [...]
> > > > > +int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > > > > +{
> > > > > +       struct ffa_send_direct_data msg = {
> > > > > +                       .data0 = 0xaaaaaaaa,
> > > > > +                       .data1 = 0xbbbbbbbb,
> > > > > +                       .data2 = 0xcccccccc,
> > > > > +                       .data3 = 0xdddddddd,
> > > > > +                       .data4 = 0xeeeeeeee,
> > > > > +       };
> > > > > +       u16 part_id;
> > > > > +       int ret;
> > > > > +       struct udevice *dev;
> > > > > +
> > > > > +       if (argc != 2) {
> > > > > +               log_err("Missing argument\n");
> > > > > +               return CMD_RET_USAGE;
> > > > > +       }
> > > > > +
> > > > > +       errno = 0;
> > > > > +       part_id = strtoul(argv[1], NULL, 16);
> > > > > +
> > > > > +       if (errno) {
> > > >
> > > > Is errno used in strtoul?
> > >
> > > Yes, please refer to [1].
> > >
> > > [1]: https://man7.org/linux/man-pages/man3/strtoul.3.html
> >
> >
> > that's what the libc version does.  Can you check the u-boot version?
> >
>
> Short answer: errno not used in strtoul() an I'm gonna remove the errno check.
>
> More details:
>
> strtoul() is defined as simple_strtoul() in strto.c
> errno variable is not set by simple_strtoul() or its callees.
> errno.h is included by strto.c to access the error codes.
>
> > > >
> ...
> > > > > +int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> > > > > +{
> > > > > +       struct udevice *dev;
> > > > > +       int ret;
> > > > > +
> > > > > +       ret = ffa_get_dev(&dev);
> > > > > +       if (ret)
> > > > > +               return CMD_RET_FAILURE;
> > > > > +
> > > > > +       log_info("device name %s, dev %p, driver name %s, ops %p\n",
> > > > > +                dev->name,
> > > > > +               (void *)map_to_sysmem(dev),
> > > > > +                dev->driver->name,
> > > > > +                (void *)map_to_sysmem(dev->driver->ops));
> > > >
> > > > Isn't it more useful to print the physical address map_to_sysmem() retuns?
> > >
> > > That's what map_to_sysmem() does, it returns a physical address and it's  shown in the log.
> >
> > I dont have access to u-boot source right, but why do you need all
> > these void * casts then?
>
> Because map_to_sysmem() returns an 'phys_addr_t' (aka 'long long unsigned int') . However, %p expects 'void *'.
>
> Compilation warning:
>
> cmd/armffa.c:181:18: warning: format ‘%p’ expects argument of type ‘void *’, but argument 3 has type ‘phys_addr_t’ {aka ‘long long unsigned int’} [8;
> ;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat=-Wformat=8;;]
>   181 |         log_info("device name %s, dev %p, driver name %s, ops %p\n",
>       |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>   182 |                  dev->name,
>   183 |                  map_to_sysmem(dev),
>       |                  ~~~~~~~~~~~~~~~~~~
>       |                  |
>       |                  phys_addr_t {aka long long unsigned int}

You should be using %lx with map_to_sysmen() since it returns a . Use
%p for pointers.

In general in U-Boot we use addresses (ulong) rather than pointers.
Unfortunately the phys_addr_t type can be larger than the word size. I
suggest creating a printf prefix for that type. See the top of blk.h
for an example of how to do it. Perhaps in a follow-up patch?

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 05/10] arm_ffa: introduce armffa command
  2023-07-03 13:30                                                                                                               ` Simon Glass
@ 2023-07-03 15:53                                                                                                                 ` Abdellatif El Khlifi
  2023-07-04  2:40                                                                                                                   ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-03 15:53 UTC (permalink / raw)
  To: Simon Glass, ilias.apalodimas; +Cc: nd, u-boot

Hi Simon, Ilias,

On Mon, Jul 03, 2023 at 02:30:51PM +0100, Simon Glass wrote:
...
> > > > > > +       log_info("device name %s, dev %p, driver name %s, ops %p\n",
> > > > > > +                dev->name,
> > > > > > +               (void *)map_to_sysmem(dev),
> > > > > > +                dev->driver->name,
> > > > > > +                (void *)map_to_sysmem(dev->driver->ops));
> > > > >
> > > > > Isn't it more useful to print the physical address map_to_sysmem() retuns?
> > > >
> > > > That's what map_to_sysmem() does, it returns a physical address and it's  shown in the log.
> > >
> > > I dont have access to u-boot source right, but why do you need all
> > > these void * casts then?
> >
> > Because map_to_sysmem() returns an 'phys_addr_t' (aka 'long long unsigned int') . However, %p expects 'void *'.
> >
> > Compilation warning:
> >
> > cmd/armffa.c:181:18: warning: format ‘%p’ expects argument of type ‘void *’, but argument 3 has type ‘phys_addr_t’ {aka ‘long long unsigned int’} [8;
> > ;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat=-Wformat=8;;]
> >   181 |         log_info("device name %s, dev %p, driver name %s, ops %p\n",
> >       |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >   182 |                  dev->name,
> >   183 |                  map_to_sysmem(dev),
> >       |                  ~~~~~~~~~~~~~~~~~~
> >       |                  |
> >       |                  phys_addr_t {aka long long unsigned int}
> 
> You should be using %lx with map_to_sysmen() since it returns a . Use
> %p for pointers.
> 
> In general in U-Boot we use addresses (ulong) rather than pointers.
> Unfortunately the phys_addr_t type can be larger than the word size. I
> suggest creating a printf prefix for that type. See the top of blk.h
> for an example of how to do it. Perhaps in a follow-up patch?
> 

Sounds good. I'm gonna add it in a generic way under include/log.h if that makes sense:

        #ifdef CONFIG_PHYS_64BIT
        #define PhysAddrLength "ll"
        #else
        #define PhysAddrLength ""
        #endif
        #define PHYS_ADDR_LN "%" PhysAddrLength "x"
        #define PHYS_ADDR_LNU "%" PhysAddrLength "u"
        #endif

Note: In a 32-bit platform phys_addr_t is "unsigned int", in a 64-bit platform it is "long long unsigned int"

Then using it this way:

        log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",
            dev->name,
            map_to_sysmem(dev),
            dev->driver->name,
            map_to_sysmem(dev->driver->ops));

Cheers
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v13 05/10] arm_ffa: introduce armffa command
  2023-07-03 15:53                                                                                                                 ` Abdellatif El Khlifi
@ 2023-07-04  2:40                                                                                                                   ` Simon Glass
  2023-07-07 14:43                                                                                                                     ` [PATCH v14 00/11] introduce Arm FF-A support Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-07-04  2:40 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: ilias.apalodimas, nd, u-boot

On Mon, 3 Jul 2023 at 16:53, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Hi Simon, Ilias,
>
> On Mon, Jul 03, 2023 at 02:30:51PM +0100, Simon Glass wrote:
> ...
> > > > > > > +       log_info("device name %s, dev %p, driver name %s, ops %p\n",
> > > > > > > +                dev->name,
> > > > > > > +               (void *)map_to_sysmem(dev),
> > > > > > > +                dev->driver->name,
> > > > > > > +                (void *)map_to_sysmem(dev->driver->ops));
> > > > > >
> > > > > > Isn't it more useful to print the physical address map_to_sysmem() retuns?
> > > > >
> > > > > That's what map_to_sysmem() does, it returns a physical address and it's  shown in the log.
> > > >
> > > > I dont have access to u-boot source right, but why do you need all
> > > > these void * casts then?
> > >
> > > Because map_to_sysmem() returns an 'phys_addr_t' (aka 'long long unsigned int') . However, %p expects 'void *'.
> > >
> > > Compilation warning:
> > >
> > > cmd/armffa.c:181:18: warning: format ‘%p’ expects argument of type ‘void *’, but argument 3 has type ‘phys_addr_t’ {aka ‘long long unsigned int’} [8;
> > > ;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat=-Wformat=8;;]
> > >   181 |         log_info("device name %s, dev %p, driver name %s, ops %p\n",
> > >       |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > >   182 |                  dev->name,
> > >   183 |                  map_to_sysmem(dev),
> > >       |                  ~~~~~~~~~~~~~~~~~~
> > >       |                  |
> > >       |                  phys_addr_t {aka long long unsigned int}
> >
> > You should be using %lx with map_to_sysmen() since it returns a . Use
> > %p for pointers.
> >
> > In general in U-Boot we use addresses (ulong) rather than pointers.
> > Unfortunately the phys_addr_t type can be larger than the word size. I
> > suggest creating a printf prefix for that type. See the top of blk.h
> > for an example of how to do it. Perhaps in a follow-up patch?
> >
>
> Sounds good. I'm gonna add it in a generic way under include/log.h if that makes sense:
>
>         #ifdef CONFIG_PHYS_64BIT
>         #define PhysAddrLength "ll"
>         #else
>         #define PhysAddrLength ""
>         #endif
>         #define PHYS_ADDR_LN "%" PhysAddrLength "x"
>         #define PHYS_ADDR_LNU "%" PhysAddrLength "u"
>         #endif
>
> Note: In a 32-bit platform phys_addr_t is "unsigned int", in a 64-bit platform it is "long long unsigned int"
>
> Then using it this way:
>
>         log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",
>             dev->name,
>             map_to_sysmem(dev),
>             dev->driver->name,
>             map_to_sysmem(dev->driver->ops));

LGTM thanks

>
> Cheers
> Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v14 00/11] introduce Arm FF-A support
  2023-07-04  2:40                                                                                                                   ` Simon Glass
@ 2023-07-07 14:43                                                                                                                     ` Abdellatif El Khlifi
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 01/11] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                                                                                                         ` (10 more replies)
  0 siblings, 11 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-07 14:43 UTC (permalink / raw)
  To: sjg
  Cc: trini, abdellatif.elkhlifi, ilias.apalodimas, nd, u-boot,
	Rob Herring, Jens Wiklander, Achin Gupta, Drew Reed,
	Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].

FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
communicate with each other. A partition could be a VM in the Normal or Secure world, an
application in S-EL0, or a Trusted OS in S-EL1.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

   => dm tree

    Class     Index  Probed  Driver                Name
   -----------------------------------------------------------
   ...
    firmware      0  [ + ]   psci                      |-- psci
    ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
   ...

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

This implementation of the specification provides support for Aarch64.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

    - Discover the presence of secure partitions (SPs) of interest
    - Access an SP's service through communication protocols
      (e.g: EFI MM communication protocol)

The FF-A support provides the following features:

    - Being generic by design and can be used by any Arm 64-bit platform
    - FF-A support can be compiled and used without EFI
    - Support for SMCCCv1.2 x0-x17 registers
    - Support for SMC32 calling convention
    - Support for 32-bit and 64-bit FF-A direct messaging
    - Support for FF-A MM communication (compatible with EFI boot time)
    - Enabling FF-A and MM communication in Corstone1000 platform as a use case
    - 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.
    - Sandbox FF-A test cases.
    - A new command called armffa is provided as an example of how to access the
      FF-A bus

For more details about the FF-A support please refer to [B] and refer to [C] for
how to use the armffa command.

Please find at [D] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of changes:
===========================

v14:

Simon:

    * add to log.h a generic physical address formatting

Ilias:

    * armffa command: in do_ffa_ping() reject the SP ID if it's 0
    * MM comms: drop truncating var_payload->size when using FF-A
    * MM comms: map the MM SP return codes to errnos
    * address nits

v13: [13]

Ilias:
    * remove FF-A and Optee ifdefs in efi_variable_tee.c
    * doc minor change: specify in the readme that the user
       should call ffa_rxtx_unmap() driver operation to unmap
       the RX/TX buffers on demand.

v12: [12]

* remove the global variable (dscvry_info), use uc_priv instead
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* remove reparenting by making the sandbox emulator parent of the FF-A device in the DT
* improve argument checks for the armffa command
* address nits

v11: [11]

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* use U_BOOT_CMD_WITH_SUBCMDS for armffa command
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device
* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* use ut_asserteq_mem() in uuid_str_to_le_bin test case
* address nits

v10: [10]

* provide the FF-A driver operations through the Uclass (arm-ffa-uclass.c)
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c renamed from core.c)
* split the FF-A sandbox support into an emulator (ffa-emul-uclass.c) and a driver (sandbox_ffa.c)
* use the FF-A driver Uclass operations by clients (armffa command, tests, MM comms)
* use uclass_first_device to search and probe the FF-A device (whether it is on Arm or on sandbox)
* address nits

v9: [9]

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
* align FF-A sandbox driver with FF-A discovery through DM
* use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
* add documentation for the armffa command: doc/usage/cmd/armffa.rst
* introduce testcase for uuid_str_to_le_bin

v8: [8]

* pass the FF-A bus device to the bus operations
* isolate the compilation choices between FF-A and OP-TEE
* drop OP-TEE configs from Corstone-1000 defconfig
* make ffa_get_partitions_info() second argument to be an SP count in both
  modes

v7: [7]

* add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v6: [6]

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

List of previous patches:

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
[7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
[8]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
[9]: https://lore.kernel.org/all/20230310141016.137986-1-abdellatif.elkhlifi@arm.com/
[10]: https://lore.kernel.org/all/20230328161157.219375-1-abdellatif.elkhlifi@arm.com/
[11]: https://lore.kernel.org/all/20230412094245.44674-1-abdellatif.elkhlifi@arm.com/
[12]: https://lore.kernel.org/all/20230512121044.111574-1-abdellatif.elkhlifi@arm.com/
[13]: https://lore.kernel.org/all/20230616152817.319869-1-abdellatif.elkhlifi@arm.com/

More details:

[A]: https://developer.arm.com/documentation/den0077/latest/
[B]: doc/arch/arm64.ffa.rst
[C]: doc/usage/cmd/armffa.rst
[D]: example of boot logs when enabling FF-A

```
   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64

   DRAM:  2 GiB
   Arm FF-A framework discovery
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   ...
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   EFI: MM partition ID 0x8003
   ...
   EFI stub: Booting Linux Kernel...
   ...
   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
   Machine model: ARM Corstone1000 FPGA MPS3 board
```

Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (11):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce uuid_str_to_le_bin function
  lib: uuid: introduce testcase for uuid_str_to_le_bin
  arm_ffa: introduce Arm FF-A support
  log: select physical address formatting in a generic way
  arm_ffa: introduce armffa command
  arm_ffa: introduce sandbox FF-A support
  arm_ffa: introduce sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   18 +
 arch/arm/cpu/armv8/smccc-call.S               |   57 +-
 arch/arm/lib/asm-offsets.c                    |   16 +
 arch/sandbox/dts/sandbox.dtsi                 |    9 +
 arch/sandbox/dts/test.dts                     |    8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |   72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        |  121 ++
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    1 +
 cmd/armffa.c                                  |  194 +++
 configs/corstone1000_defconfig                |    1 +
 configs/sandbox64_defconfig                   |    1 +
 configs/sandbox_defconfig                     |    1 +
 doc/arch/arm64.ffa.rst                        |  261 ++++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox/sandbox.rst                  |    1 +
 doc/usage/cmd/armffa.rst                      |   93 ++
 doc/usage/index.rst                           |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   42 +
 drivers/firmware/arm-ffa/Makefile             |   16 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 drivers/firmware/arm-ffa/ffa-emul-uclass.c    |  720 +++++++++++
 drivers/firmware/arm-ffa/sandbox_ffa.c        |  110 ++
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/configs/corstone1000.h                |   15 +-
 include/dm/uclass-id.h                        |    7 +
 include/linux/arm-smccc.h                     |   45 +
 include/log.h                                 |    8 +
 include/mm_communication.h                    |   13 +
 include/uuid.h                                |   15 +
 lib/efi_loader/Kconfig                        |   16 +-
 lib/efi_loader/efi_variable_tee.c             |  272 ++++-
 lib/uuid.c                                    |   48 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   33 +
 test/dm/Makefile                              |    3 +-
 test/dm/ffa.c                                 |  261 ++++
 test/lib/Makefile                             |    1 +
 test/lib/uuid.c                               |   41 +
 43 files changed, 4153 insertions(+), 11 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 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 doc/usage/cmd/armffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/lib/uuid.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v14 01/11] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-07-07 14:43                                                                                                                     ` [PATCH v14 00/11] introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-07-07 14:44                                                                                                                       ` Abdellatif El Khlifi
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 02/11] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
                                                                                                                                         ` (9 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-07 14:44 UTC (permalink / raw)
  To: sjg
  Cc: trini, abdellatif.elkhlifi, ilias.apalodimas, nd, u-boot, Jens Wiklander

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>

---

Changelog:
===============

v9:

* update the copyright string

v7:

* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

 arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
 arch/arm/lib/asm-offsets.c      | 16 +++++++++
 include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..93f66d3366 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,7 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
- */
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+*/
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
 #include <generated/asm-offsets.h>
@@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 6de0ce9152..181a8ac4c2 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,11 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * 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>
@@ -90,6 +95,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#ifdef CONFIG_ARM64
+	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..f44e9e8f93 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +74,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v14 02/11] lib: uuid: introduce uuid_str_to_le_bin function
  2023-07-07 14:43                                                                                                                     ` [PATCH v14 00/11] introduce Arm FF-A support Abdellatif El Khlifi
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 01/11] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-07-07 14:44                                                                                                                       ` Abdellatif El Khlifi
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 03/11] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
                                                                                                                                         ` (8 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-07 14:44 UTC (permalink / raw)
  To: sjg
  Cc: trini, abdellatif.elkhlifi, ilias.apalodimas, nd, u-boot, Jens Wiklander

convert UUID string to little endian binary data

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v9:

* add a full function prototype description in uuid.h

v8:

* use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

 include/uuid.h | 15 +++++++++++++++
 lib/uuid.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..89b93e642b 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,10 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +48,15 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ * Return:
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 96e1af3c8b..45f325d964 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * 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>
@@ -354,6 +358,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16;
+	u32 tmp32;
+	u64 tmp64;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+	memcpy(uuid_bin, &tmp32, 4);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16));
+	memcpy(uuid_bin + 10, &tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v14 03/11] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-07-07 14:43                                                                                                                     ` [PATCH v14 00/11] introduce Arm FF-A support Abdellatif El Khlifi
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 01/11] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 02/11] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2023-07-07 14:44                                                                                                                       ` Abdellatif El Khlifi
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 04/11] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                         ` (7 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-07 14:44 UTC (permalink / raw)
  To: sjg; +Cc: trini, abdellatif.elkhlifi, ilias.apalodimas, nd, u-boot

provide a test case

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>

---

Changelog:
===============

v11:

* use ut_asserteq_mem()

 MAINTAINERS       |  5 +++++
 test/lib/Makefile |  1 +
 test/lib/uuid.c   | 41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)
 create mode 100644 test/lib/uuid.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d724b64673..a1e34ab63a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1634,3 +1634,8 @@ S:	Maintained
 F:	arch/arm/dts/ls1021a-twr-u-boot.dtsi
 F:	drivers/crypto/fsl/
 F:	include/fsl_sec.h
+
+UUID testing
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	test/lib/uuid.c
diff --git a/test/lib/Makefile b/test/lib/Makefile
index e0bd9e04e8..e75a263e6a 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_AES) += test_aes.o
 obj-$(CONFIG_GETOPT) += getopt.o
 obj-$(CONFIG_CRC8) += test_crc8.o
 obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o
+obj-$(CONFIG_LIB_UUID) += uuid.o
 else
 obj-$(CONFIG_SANDBOX) += kconfig_spl.o
 endif
diff --git a/test/lib/uuid.c b/test/lib/uuid.c
new file mode 100644
index 0000000000..e24331a136
--- /dev/null
+++ b/test/lib/uuid.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <uuid.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* test UUID */
+#define TEST_SVC_UUID	"ed32d533-4209-99e6-2d72-cdd998a79cc0"
+
+#define UUID_SIZE 16
+
+/* The UUID binary data (little-endian format) */
+static const u8 ref_uuid_bin[UUID_SIZE] = {
+	0x33, 0xd5, 0x32, 0xed,
+	0x09, 0x42, 0xe6, 0x99,
+	0x72, 0x2d, 0xc0, 0x9c,
+	0xa7, 0x98, 0xd9, 0xcd
+};
+
+static int lib_test_uuid_to_le(struct unit_test_state *uts)
+{
+	const char *uuid_str = TEST_SVC_UUID;
+	u8 ret_uuid_bin[UUID_SIZE] = {0};
+
+	ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin));
+	ut_asserteq_mem(ref_uuid_bin, ret_uuid_bin, UUID_SIZE);
+
+	return 0;
+}
+
+LIB_TEST(lib_test_uuid_to_le, 0);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v14 04/11] arm_ffa: introduce Arm FF-A support
  2023-07-07 14:43                                                                                                                     ` [PATCH v14 00/11] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                         ` (2 preceding siblings ...)
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 03/11] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-07-07 14:44                                                                                                                       ` Abdellatif El Khlifi
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 05/11] log: select physical address formatting in a generic way Abdellatif El Khlifi
                                                                                                                                         ` (6 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-07 14:44 UTC (permalink / raw)
  To: sjg
  Cc: trini, abdellatif.elkhlifi, ilias.apalodimas, nd, u-boot,
	Jens Wiklander, Heinrich Schuchardt

Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- ffa_partition_info_get
- ffa_sync_send_receive
- ffa_rxtx_unmap

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 please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v13:

* doc minor change: specify in the readme that the user
   should call ffa_rxtx_unmap() driver operation to unmap
   the RX/TX buffers on demand.

v12:

* remove dscvry_info
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* address nits

v11:

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* pass dev as an argument of arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* add emul field in struct ffa_discovery_info
* address nits

v10:

* provide the driver operations through the Uclass
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c)
* rename core.c to arm-ffa.c
* address nits

v9:

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding

v8:

* make ffa_get_partitions_info() second argument to be an SP count in both
  modes
* update ffa_bus_prvdata_get() to return a pointer rather than a pointer
  address
* remove packing from ffa_partition_info and ffa_send_direct_data structures
* pass the FF-A bus device to the bus operations

v7:

* add support for 32-bit direct messaging
* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* improve the declaration of error handling mapping
* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the U-Boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the U-Boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

 MAINTAINERS                                   |    8 +
 doc/arch/arm64.ffa.rst                        |  238 ++++
 doc/arch/index.rst                            |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   36 +
 drivers/firmware/arm-ffa/Makefile             |    8 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |   14 +
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/dm/uclass-id.h                        |    6 +
 13 files changed, 1941 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h

diff --git a/MAINTAINERS b/MAINTAINERS
index a1e34ab63a..b3a16ed802 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,6 +266,14 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+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>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..4f817f053c
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,238 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Support
+================
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
+communicate with each other. A partition could be a VM in the Normal or Secure world, an
+application in S-EL0, or a Trusted OS in S-EL1.
+
+The U-Boot FF-A support (the bus) implements the interfaces to communicate
+with partitions in the Secure world aka Secure partitions (SPs).
+
+The FF-A support specifically focuses on communicating with SPs that
+isolate portions of EFI runtime services that must run in a protected
+environment which is inaccessible by the Host OS or Hypervisor.
+Examples of such services are set/get variables.
+
+The FF-A support uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+At this stage of development only EFI boot-time services are supported.
+Runtime support will be added in future developments.
+
+The U-Boot FF-A support provides the following parts:
+
+- A Uclass driver providing generic FF-A methods.
+- An Arm FF-A device driver providing Arm-specific methods and reusing the Uclass methods.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the U-Boot FF-A support relies on
+`FF-A v1.0 specification`_ and uses SMC32 calling convention which
+means using the first 32-bit data of the Xn registers.
+
+At this stage we only need the FF-A v1.0 features.
+
+The FF-A support has been tested with OP-TEE which supports SMC32 calling
+convention.
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A support uses 64-bit registers as per `SMC Calling Convention v1.2 specification`_.
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+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.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers.
+Then, an SMC instruction is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-Boot Arm FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs.
+
+FF-A bus discovery on Arm 64-bit platforms
+---------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
+an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
+This discovery mechanism is performed by the PSCI driver.
+
+The PSCI driver comes with a PSCI device tree node which is the root node for all
+architecture features including FF-A bus.
+
+::
+
+   => dm tree
+
+    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.
+
+In case of FF-A, the callback is arm_ffa_is_supported() which tries to discover the
+FF-A framework by querying the FF-A framework version from secure world using
+FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
+mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver
+with the device using device_bind_driver().
+
+At this stage the FF-A bus is registered with the DM and can be interacted with using
+the DM APIs.
+
+Clients are able to probe then use the FF-A bus by calling uclass_first_device().
+Please refer to the armffa command implementation as an example of how to probe
+and interact with the FF-A bus.
+
+When calling uclass_first_device(), the FF-A driver is probed and ends up calling
+ffa_do_probe() provided by the Uclass which does the following:
+
+    - saving the FF-A framework version in uc_priv
+    - querying from secure world the u-boot endpoint ID
+    - querying from secure world the supported features of FFA_RXTX_MAP
+    - mapping the RX/TX buffers
+    - querying from secure world all the partitions information
+
+When one of the above actions fails, probing fails and the driver stays not active
+and can be probed again if needed.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must query the SPs they are looking for
+during EFI boot-time mode using the service UUID.
+
+The RX/TX buffers are only available at EFI boot-time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped before EFI runtime mode starts.
+The driver provides a bus operation for that called ffa_rxtx_unmap().
+
+The user should call ffa_rxtx_unmap() to unmap the RX/TX buffers when required
+(e.g: at efi_exit_boot_services()).
+
+The Linux kernel allocates its own RX/TX buffers. To be able to register these kernel buffers
+with secure world, the U-Boot's RX/TX buffers should be unmapped before EFI runtime starts.
+
+When invoking FF-A direct messaging, clients should specify which ABI protocol
+they want to use (32-bit vs 64-bit). Selecting the protocol means using
+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
+The calling convention between U-Boot and the secure world stays the same: SMC32.
+
+Requirements for user drivers
+-------------------------------------
+
+Users who want to implement their custom FF-A device driver while reusing the FF-A Uclass can do so
+by implementing their own invoke_ffa_fn() in the user driver.
+
+The bus driver layer
+------------------------------
+
+FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c
+
+The following features are provided:
+
+- Support for the 32-bit version of the following ABIs:
+
+    - FFA_VERSION
+    - FFA_ID_GET
+    - FFA_FEATURES
+    - FFA_PARTITION_INFO_GET
+    - FFA_RXTX_UNMAP
+    - FFA_RX_RELEASE
+    - FFA_RUN
+    - FFA_ERROR
+    - FFA_SUCCESS
+    - FFA_INTERRUPT
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Support for the 64-bit version of the following ABIs:
+
+    - FFA_RXTX_MAP
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, FF-A support takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- FF-A support provides driver operations to be used by upper layers:
+
+    - ffa_partition_info_get
+    - ffa_sync_send_receive
+    - ffa_rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+Example of boot logs with FF-A enabled
+--------------------------------------
+
+For example, when using FF-A with Corstone-1000 the logs are as follows:
+
+::
+
+   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64
+
+   DRAM:  2 GiB
+   Arm FF-A framework discovery
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   ...
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   EFI: MM partition ID 0x8003
+   ...
+   EFI stub: Booting Linux Kernel...
+   ...
+   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
+   Machine model: ARM Corstone1000 FPGA MPS3 board
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+
+.. _`FF-A v1.0 specification`: https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e
+.. _`SMC Calling Convention v1.2 specification`: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index b8da4b8c8e..2f916f4026 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Makefile b/drivers/Makefile
index 78dcf62f76..5044f45253 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -115,6 +115,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index eae1c8ddc9..8789b1ea14 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
 	  the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
 	  services if any and reported as supported by the SMCCC firmware.
 
+source "drivers/firmware/arm-ffa/Kconfig"
 source "drivers/firmware/scmi/Kconfig"
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..9200c8028b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select ARM_SMCCC_FEATURES
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
+	  FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
+	  by the PSCI driver.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  The FF-A support on U-Boot  takes care of all the interactions between Normal
+	  world and Secure World.
+
+	  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
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..11b1766285
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,8 @@
+# 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>
+
+obj-y += arm-ffa-uclass.o arm-ffa.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..ffa9d81fa7
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,1065 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	[NOT_SUPPORTED] = -EOPNOTSUPP,
+	[INVALID_PARAMETERS] = -EINVAL,
+	[NO_MEMORY] = -ENOMEM,
+	[BUSY] = -EBUSY,
+	[INTERRUPTED] = -EINTR,
+	[DENIED] = -EACCES,
+	[RETRY] = -EAGAIN,
+	[ABORTED] = -ECANCELED,
+};
+
+static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			[NO_MEMORY] =
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			[BUSY] =
+			"BUSY: RX buffer of the caller is not free",
+			[DENIED] =
+			"DENIED: Callee is not in a state to handle this request",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			[DENIED] =
+			"DENIED: Caller did not have ownership of the RX buffer",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			[NO_MEMORY] =
+			"NO_MEMORY: Not enough memory",
+			[DENIED] =
+			"DENIED: Buffer pair already registered",
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno() - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+static int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* Map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+static int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* Map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	log_err("%s\n", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/* FF-A ABIs implementation (U-Boot side) */
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void __weak invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+}
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	log_info("FF-A driver %d.%d\nFF-A framework %d.%d\n",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) {
+		log_info("FF-A versions are compatible\n");
+
+		if (dev) {
+			uc_priv = dev_get_uclass_priv(dev);
+			if (uc_priv)
+				uc_priv->fwk_version = res.a0;
+		}
+
+		return 0;
+	}
+
+	log_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id() - FFA_ID_GET handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		uc_priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		log_debug("FF-A endpoint ID is %u\n", uc_priv->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt() - set the minimum number of pages in each of the RX/TX buffers
+ * @dev: The FF-A bus device
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * Set the minimum number of pages in each of the RX/TX buffers in uc_priv
+ *
+ * Return:
+ *
+ * rxtx_min_pages field contains the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	switch (prop_field) {
+	case RXTX_4K:
+		uc_priv->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		uc_priv->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		uc_priv->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		log_err("RX/TX buffer size not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features_hdlr() - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_FEATURES FF-A function to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers() - free the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Free the RX/TX buffers
+ */
+static void ffa_free_rxtx_buffers(struct udevice *dev)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Freeing FF-A RX/TX buffers\n");
+
+	if (uc_priv->pair.rxbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+	}
+
+	if (uc_priv->pair.txbuf) {
+		free(uc_priv->pair.txbuf);
+		uc_priv->pair.txbuf = NULL;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers() - allocate the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ * The size of the memory allocated is the minimum allowed.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(struct udevice *dev)
+{
+	u64 bytes;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Using %lu 4KB page(s) for FF-A RX/TX buffers size\n",
+		  uc_priv->pair.rxtx_min_pages);
+
+	bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 * Assumption: Memory allocated with memalign is always physically contiguous
+	 */
+
+	uc_priv->pair.rxbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.rxbuf) {
+		log_err("failure to allocate RX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A RX buffer at virtual address %p\n", uc_priv->pair.rxbuf);
+
+	uc_priv->pair.txbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.txbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+		log_err("failure to allocate the TX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A TX buffer at virtual address %p\n", uc_priv->pair.txbuf);
+
+	/* Make sure the buffers are cleared before use */
+	memset(uc_priv->pair.rxbuf, 0, bytes);
+	memset(uc_priv->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers_hdlr() - FFA_RXTX_MAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_MAP FF-A function to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	ret = ffa_alloc_rxtx_buffers(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 * no need to convert from virtual to physical
+	 */
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = map_to_sysmem(uc_priv->pair.txbuf),
+			.a2 = map_to_sysmem(uc_priv->pair.rxbuf),
+			.a3 = uc_priv->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		log_debug("FF-A RX/TX buffers mapped\n");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers(dev);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_UNMAP FF-A function to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	log_debug("unmapping FF-A RX/TX buffers\n");
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers(dev);
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer_hdlr() - FFA_RX_RELEASE handler function
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_RX_RELEASE FF-A function to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical() - check whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * Used by ffa_read_partitions_info to search for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+static bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+				   const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info() - read queried partition data
+ * @dev: The FF-A bus device
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * Read the partitions information returned by the FFA_PARTITION_INFO_GET and saves it in uc_priv
+ *
+ * Return:
+ *
+ * uc_priv is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(struct udevice *dev, u32 count,
+				    struct ffa_partition_uuid *part_uuid)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	if (!count) {
+		log_err("no partition detected\n");
+		return -ENODATA;
+	}
+
+	log_debug("Reading FF-A partitions data from the RX buffer\n");
+
+	if (!part_uuid) {
+		/* Querying information of all partitions */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			log_err("partitions data size exceeds the RX buffer size:\n");
+			log_err("    sizes in bytes: data %llu , RX buffer %llu\n",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		uc_priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO);
+		if (!uc_priv->partitions.descs) {
+			log_err("cannot  allocate partitions data buffer\n");
+			return -ENOMEM;
+		}
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			uc_priv->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			log_debug("FF-A partition ID %x : info cached\n",
+				  uc_priv->partitions.descs[desc_idx].info.id);
+		}
+
+		uc_priv->partitions.count = count;
+
+		log_debug("%d FF-A partition(s) found and cached\n", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		/*
+		 * Search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/* Search the current ID in the cached partitions */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < uc_priv->partitions.count;
+			     cached_desc_idx++) {
+				/* Save the UUID */
+				if (uc_priv->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					uc_priv->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info() - invoke FFA_PARTITION_INFO_GET and save partitions data
+ * @dev: The FF-A bus device
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * Execute the FFA_PARTITION_INFO_GET to query the partitions data.
+ * Then, call ffa_read_partitions_info to save the data in uc_priv.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid);
+			if (ret) {
+				log_err("failed reading SP(s) data , err (%d)\n", ret);
+				ffa_release_rx_buffer_hdlr(dev);
+				return -EINVAL;
+			}
+		}
+
+		/* Return the SP count (when querying using a UUID) */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer_hdlr(dev);
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET FF-A function to query the partition information
+ * from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * If the partition(s) matching the UUID found, the partition(s) information and the
+ * number are returned.
+ * If no partition matching the UUID is found in the cached area, a new FFA_PARTITION_INFO_GET
+ * call is issued.
+ * If not done yet, the UUID is updated in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	u32 i;
+	struct ffa_partition_uuid part_uuid = {0};
+	struct ffa_priv *uc_priv;
+	struct ffa_partition_desc *rx_descs;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs) {
+		log_err("no partition installed\n");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		log_err("no UUID provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_count) {
+		log_err("no count argument provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_descs) {
+		log_err("no info argument provided\n");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		log_err("invalid UUID\n");
+		return -EINVAL;
+	}
+
+	log_debug("Searching FF-A partitions using the provided UUID\n");
+
+	*sp_count = 0;
+	*sp_descs = uc_priv->pair.rxbuf;
+	rx_descs = *sp_descs;
+
+	/* Search in the cached partitions */
+	for (i = 0; i < uc_priv->partitions.count; i++)
+		if (ffa_uuid_are_identical(&uc_priv->partitions.descs[i].sp_uuid,
+					   &part_uuid)) {
+			log_debug("FF-A partition ID %x matches the provided UUID\n",
+				  uc_priv->partitions.descs[i].info.id);
+
+			(*sp_count)++;
+			*rx_descs++ = uc_priv->partitions.descs[i];
+			}
+
+	if (!(*sp_count)) {
+		int ret;
+
+		log_debug("No FF-A partition found. Querying framework ...\n");
+
+		ret = ffa_query_partitions_info(dev, &part_uuid, sp_count);
+
+		if (!ret) {
+			log_debug("Number of FF-A partition(s) matching the UUID: %d\n", *sp_count);
+
+			if (*sp_count)
+				ret = ffa_get_partitions_info_hdlr(dev, uuid_str, sp_count,
+								   sp_descs);
+			else
+				ret = -ENODATA;
+		}
+
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info() - Query and saves all secure partitions data
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_PARTITION_INFO_GET FF-A function to query from secure world
+ * all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in uc_priv
+ * and we keep the UUID field empty (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * Called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(struct udevice *dev)
+{
+	return ffa_query_partitions_info(dev, NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Implement FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u64 req_mode, resp_mode;
+	struct ffa_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* No partition installed */
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs)
+		return -ENODEV;
+
+	if (is_smc64) {
+		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+	} else {
+		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = req_mode,
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == resp_mode) {
+		/* Message sent with response extract the return data */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/* FF-A driver operations (used by clients for communicating with FF-A)*/
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Driver operation for FFA_PARTITION_INFO_GET.
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->partition_info_get)
+		return -ENOSYS;
+
+	return ops->partition_info_get(dev, uuid_str, sp_count, sp_descs);
+}
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Driver operation for FFA_MSG_SEND_DIRECT_{REQ,RESP}.
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->sync_send_receive)
+		return -ENOSYS;
+
+	return ops->sync_send_receive(dev, dst_part_id, msg, is_smc64);
+}
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * @dev: The FF-A bus device
+ *
+ * Driver operation for FFA_RXTX_UNMAP.
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_rxtx_unmap(struct udevice *dev)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->rxtx_unmap)
+		return -ENOSYS;
+
+	return ops->rxtx_unmap(dev);
+}
+
+/**
+ * ffa_do_probe() - probing FF-A framework
+ * @dev:	the FF-A bus device (arm_ffa)
+ *
+ * Probing is triggered on demand by clients searching for the uclass.
+ * At probe level the following actions are done:
+ *	- saving the FF-A framework version in uc_priv
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in uc_priv.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_do_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_endpoint_id(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_cache_partitions_info(dev);
+	if (ret) {
+		ffa_unmap_rxtx_buffers_hdlr(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+UCLASS_DRIVER(ffa) = {
+	.name			= "ffa",
+	.id			= UCLASS_FFA,
+	.pre_probe		= ffa_do_probe,
+	.pre_remove		= ffa_unmap_rxtx_buffers_hdlr,
+	.per_device_auto	= sizeof(struct ffa_priv)
+};
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
new file mode 100644
index 0000000000..68df75bd9e
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -0,0 +1,104 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <linux/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * 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 low level SMC assembly function
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * arm_ffa_discover() - perform FF-A discovery
+ * @dev: The Arm FF-A bus device (arm_ffa)
+ * 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:
+ *
+ * true on success. Otherwise, false.
+ */
+static bool arm_ffa_discover(struct udevice *dev)
+{
+	int ret;
+
+	log_info("Arm FF-A framework discovery\n");
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/**
+ * arm_ffa_is_supported() - FF-A bus discovery callback
+ * @invoke_fn: legacy SMC invoke function (not used)
+ *
+ * Perform FF-A discovery by calling arm_ffa_discover().
+ * Discovery is performed by querying the FF-A framework version from
+ * secure world using the FFA_VERSION ABI.
+ *
+ * The FF-A driver is registered as an SMCCC feature driver. So, features discovery
+ * callbacks are called by the PSCI driver (PSCI device is the SMCCC features
+ * root device).
+ *
+ * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
+ * So, the legacy SMC invocation is not used.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static bool arm_ffa_is_supported(void (*invoke_fn)(ulong a0, ulong a1,
+						   ulong a2, ulong a3,
+						   ulong a4, ulong a5,
+						   ulong a6, ulong a7,
+						   struct arm_smccc_res *res))
+{
+	return arm_ffa_discover(NULL);
+}
+
+/* Arm FF-A driver operations */
+
+static const struct ffa_bus_ops 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,
+};
+
+/* Registering the FF-A driver as an SMCCC feature driver */
+
+ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
+	.driver_name = FFA_DRV_NAME,
+	.is_supported = arm_ffa_is_supported,
+};
+
+/* Declaring the FF-A driver under UCLASS_FFA */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.flags		= DM_REMOVE_OS_PREPARE,
+	.ops		= &ffa_ops,
+};
diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
new file mode 100644
index 0000000000..4338f9c9b1
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
@@ -0,0 +1,14 @@
+/* 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/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..db9b1be995
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,213 @@
+/* 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 __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
+ * @a1-4:	32-bit words access to the UUID data
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct ffa_send_direct_data {
+	ulong data0; /* w3/x3 */
+	ulong data1; /* w4/x4 */
+	ulong data2; /* w5/x5 */
+	ulong data3; /* w6/x6 */
+	ulong data4; /* w7/x7 */
+};
+
+struct udevice;
+
+/**
+ * struct ffa_bus_ops - Operations for FF-A
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
+				  u32 *sp_count, struct ffa_partition_desc **sp_descs);
+	int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg,
+				 bool is_smc64);
+	int (*rxtx_unmap)(struct udevice *dev);
+};
+
+#define ffa_get_ops(dev)        ((struct ffa_bus_ops *)(dev)->driver->ops)
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ */
+int ffa_rxtx_unmap(struct udevice *dev);
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The arm_ffa bus device
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev);
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The arm_ffa bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+struct ffa_priv;
+
+/**
+ * ffa_set_smc_conduit() - Set the SMC conduit
+ * @dev: The FF-A bus device
+ *
+ * Selects the SMC conduit by setting the FF-A ABI invoke function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_set_smc_conduit(struct udevice *dev);
+
+#endif
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
new file mode 100644
index 0000000000..d564c33c64
--- /dev/null
+++ b/include/arm_ffa_priv.h
@@ -0,0 +1,246 @@
+/* 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 __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <mapmem.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+
+/* This header is exclusively used by the FF-A Uclass and FF-A driver(s) */
+
+/* Arm FF-A driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* The FF-A SMC function definitions */
+
+#if CONFIG_IS_ENABLED(SANDBOX)
+
+/* Providing Arm SMCCC declarations to sandbox */
+
+/**
+ * struct sandbox_smccc_1_2_regs - emulated SMC call arguments or results
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct sandbox_smccc_1_2_regs {
+	ulong a0;
+	ulong a1;
+	ulong a2;
+	ulong a3;
+	ulong a4;
+	ulong a5;
+	ulong a6;
+	ulong a7;
+	ulong a8;
+	ulong a9;
+	ulong a10;
+	ulong a11;
+	ulong a12;
+	ulong a13;
+	ulong a14;
+	ulong a15;
+	ulong a16;
+	ulong a17;
+};
+
+typedef struct sandbox_smccc_1_2_regs ffa_value_t;
+
+#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))
+
+#else
+/* CONFIG_ARM64 */
+#include <linux/arm-smccc.h>
+typedef struct arm_smccc_1_2_regs ffa_value_t;
+#endif
+
+/* Defining the function pointer type for the function executing the FF-A ABIs */
+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)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR                 = 0x60,
+	FFA_SUCCESS               = 0x61,
+	FFA_INTERRUPT             = 0x62,
+	FFA_VERSION               = 0x63,
+	FFA_FEATURES              = 0x64,
+	FFA_RX_RELEASE            = 0x65,
+	FFA_RXTX_MAP              = 0x66,
+	FFA_RXTX_UNMAP            = 0x67,
+	FFA_PARTITION_INFO_GET    = 0x68,
+	FFA_ID_GET                = 0x69,
+	FFA_RUN                   = 0x6d,
+	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
+	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
+
+	/* To be updated when adding new FFA IDs */
+	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
+	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
+};
+
+enum ffa_abi_errcode {
+	NOT_SUPPORTED = 1,
+	INVALID_PARAMETERS,
+	NO_MEMORY,
+	BUSY,
+	INTERRUPTED,
+	DENIED,
+	RETRY,
+	ABORTED,
+	MAX_NUMBER_FFA_ERR
+};
+
+extern int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR];
+
+/* Container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Hosts the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	void *rxbuf; /* Virtual address returned by memalign */
+	void *txbuf; /* Virtual address returned by memalign */
+	size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */
+};
+
+struct ffa_partition_desc;
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * Contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* Virtual address */
+};
+
+/**
+ * struct ffa_priv - the driver private data structure
+ *
+ * @fwk_version:	FF-A framework version
+ * @emul:	FF-A sandbox emulator
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ *
+ * The device private data structure containing all the
+ * data read from secure world.
+ */
+struct ffa_priv {
+	u32 fwk_version;
+	struct udevice *emul;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+};
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev);
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 307ad6931c..3c6af2e3d2 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,11 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -57,6 +62,7 @@ enum uclass_id {
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_EXTCON,		/* External Connector Class */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v14 05/11] log: select physical address formatting in a generic way
  2023-07-07 14:43                                                                                                                     ` [PATCH v14 00/11] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                         ` (3 preceding siblings ...)
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 04/11] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-07-07 14:44                                                                                                                       ` Abdellatif El Khlifi
  2023-07-07 17:34                                                                                                                         ` Simon Glass
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 06/11] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                                                                                                         ` (5 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-07 14:44 UTC (permalink / raw)
  To: sjg; +Cc: trini, abdellatif.elkhlifi, ilias.apalodimas, nd, u-boot

sets the log formatting according to the platform (64-bit vs 32-bit)

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Simon Glass <sjg@chromium.org>
---
 include/log.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/log.h b/include/log.h
index 3bab40b617..689cef905b 100644
--- a/include/log.h
+++ b/include/log.h
@@ -686,4 +686,12 @@ static inline int log_get_default_format(void)
 	       (IS_ENABLED(CONFIG_LOGF_FUNC) ? BIT(LOGF_FUNC) : 0);
 }
 
+/* Select the right physical address formatting according to the platform */
+#ifdef CONFIG_PHYS_64BIT
+#define PhysAddrLength "ll"
+#else
+#define PhysAddrLength ""
+#endif
+#define PHYS_ADDR_LN "%" PhysAddrLength "x"
+#define PHYS_ADDR_LNU "%" PhysAddrLength "u"
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v14 06/11] arm_ffa: introduce armffa command
  2023-07-07 14:43                                                                                                                     ` [PATCH v14 00/11] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                         ` (4 preceding siblings ...)
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 05/11] log: select physical address formatting in a generic way Abdellatif El Khlifi
@ 2023-07-07 14:44                                                                                                                       ` Abdellatif El Khlifi
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 07/11] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
                                                                                                                                         ` (4 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-07 14:44 UTC (permalink / raw)
  To: sjg
  Cc: trini, abdellatif.elkhlifi, ilias.apalodimas, nd, u-boot,
	Jens Wiklander, Heinrich Schuchardt

Provide armffa command showcasing the use of the U-Boot FF-A support

armffa is a command showcasing how to invoke FF-A operations.
This provides a guidance to the client developers on how to
call the FF-A bus interfaces. The command also allows to gather secure
partitions information and ping these  partitions. The command is also
helpful in testing the communication with secure partitions.

For more details please refer to the command documentation [1].

[1]: doc/usage/cmd/armffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v14:

Ilias:

* address nits
* in do_ffa_ping() reject the SP ID if it's 0
* use PHYS_ADDR_LN in formatting the physical addresses

v12:

* add subcommands argument checks
* usage documentation: update command return codes
* remove calloc when querying SPs
* address nits

v11:

* use U_BOOT_CMD_WITH_SUBCMDS
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* address nits

v9:

* remove manual FF-A discovery and use DM
* use DM class APIs to probe and interact with the FF-A bus
* add doc/usage/cmd/armffa.rst

v8:

* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* adapt do_ffa_dev_list() following the recent update on
  uclass_first_device/uclass_next_device functions (they return void now)
* set armffa command to use 64-bit direct messaging

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

 MAINTAINERS                      |   2 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   1 +
 cmd/armffa.c                     | 194 +++++++++++++++++++++++++++++++
 doc/arch/arm64.ffa.rst           |   7 ++
 doc/usage/cmd/armffa.rst         |  93 +++++++++++++++
 doc/usage/index.rst              |   1 +
 drivers/firmware/arm-ffa/Kconfig |   1 +
 8 files changed, 309 insertions(+)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/usage/cmd/armffa.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index b3a16ed802..ff6a222960 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,7 +269,9 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+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
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 02e54f1e50..79b4f8367a 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -935,6 +935,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the FF-A support
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index 6c37521b4e..7d20a85a46 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,7 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_2048) += 2048.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..ab0fd54d97
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,194 @@
+// 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 <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+#include <asm/io.h>
+
+/**
+ * ffa_get_dev() - Return the FF-A device
+ * @devp:	pointer to the FF-A device
+ *
+ * Search for the FF-A device.
+ *
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_dev(struct udevice **devp)
+{
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, devp);
+	if (ret) {
+		log_err("Cannot find FF-A bus device\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * do_ffa_getpart() - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query a secure partition information. The secure partition UUID is provided
+ * as an argument. The function uses the arm_ffa driver
+ * partition_info_get operation which implements FFA_PARTITION_INFO_GET
+ * ABI to retrieve the data. The input UUID string is expected to be in big
+ * endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	u32 i;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+
+	ret = ffa_partition_info_get(dev, argv[1], &count, &descs);
+	if (ret) {
+		log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	/* SPs found , show the partition information */
+	for (i = 0; i < count ; i++) {
+		log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
+			 descs[i].info.id,
+			 descs[i].info.exec_ctxt,
+			 descs[i].info.properties);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_ffa_ping() - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Send data to a secure partition. The secure partition UUID is provided
+ * as an argument. Use the arm_ffa driver sync_send_receive operation
+ * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	part_id = strtoul(argv[1], NULL, 16);
+	if (!part_id) {
+		log_err("Partition ID can not be 0\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	if (!ret) {
+		u8 cnt;
+
+		log_info("SP response:\n[LSB]\n");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			log_info("%llx\n", ((u64 *)&msg)[cnt]);
+		return CMD_RET_SUCCESS;
+	}
+
+	log_err("Sending direct request error (%d)\n", ret);
+	return CMD_RET_FAILURE;
+}
+
+/**
+ *do_ffa_devlist() - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query the device belonging to the UCLASS_FFA
+ * class.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",
+		 dev->name,
+		 map_to_sysmem(dev),
+		 dev->driver->name,
+		 map_to_sysmem(dev->driver->ops));
+
+	return CMD_RET_SUCCESS;
+}
+
+static char armffa_help_text[] =
+	"getpart <partition UUID>\n"
+	"       - lists the partition(s) info\n"
+	"ping <partition ID>\n"
+	"       - sends a data pattern to the specified partition\n"
+	"devlist\n"
+	"       - displays information about the FF-A device/driver\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
+			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
+			U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping),
+			U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist));
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 4f817f053c..aefd527447 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -205,6 +205,13 @@ The following features are provided:
 
 - FF-A bus can be compiled and used without EFI
 
+The armffa command
+-----------------------------------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke the driver operations.
+
+Please refer the command documentation at :doc:`../usage/cmd/armffa`
+
 Example of boot logs with FF-A enabled
 --------------------------------------
 
diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
new file mode 100644
index 0000000000..3d422686c1
--- /dev/null
+++ b/doc/usage/cmd/armffa.rst
@@ -0,0 +1,93 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+armffa command
+==============
+
+Synopsis
+--------
+
+::
+
+   armffa [sub-command] [arguments]
+
+   sub-commands:
+
+        getpart [partition UUID]
+
+            lists the partition(s) info
+
+        ping [partition ID]
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays information about the FF-A device/driver
+
+Description
+-----------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
+
+The command also allows to gather secure partitions information and ping these  partitions.
+
+The command is also helpful in testing the communication with secure partitions.
+
+Example
+-------
+
+The following examples are run on Corstone-1000 platform.
+
+* ping
+
+::
+
+   corstone1000# armffa ping 0x8003
+   SP response:
+   [LSB]
+   fffffffe
+   0
+   0
+   0
+   0
+
+* ping (failure case)
+
+::
+
+   corstone1000# armffa ping 0
+   Sending direct request error (-22)
+
+* getpart
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
+   Partition: id = 8003 , exec_ctxt 1 , properties 3
+
+* getpart (failure case)
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221
+   INVALID_PARAMETERS: Unrecognized UUID
+   Failure in querying partitions count (error code: -22)
+
+* devlist
+
+::
+
+   corstone1000# armffa devlist
+   device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98
+
+Configuration
+-------------
+
+The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
+
+Return value
+------------
+
+The return value $? is 0 (true) on success, 1 (false) on failure.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 388e59f173..e462de2806 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -22,6 +22,7 @@ Shell commands
 
    cmd/acpi
    cmd/addrmap
+   cmd/armffa
    cmd/askenv
    cmd/base
    cmd/bdinfo
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index 9200c8028b..a7d5392859 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
 	depends on DM && ARM64
 	select ARM_SMCCC
 	select ARM_SMCCC_FEATURES
+	imply CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v14 07/11] arm_ffa: introduce sandbox FF-A support
  2023-07-07 14:43                                                                                                                     ` [PATCH v14 00/11] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                         ` (5 preceding siblings ...)
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 06/11] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-07-07 14:44                                                                                                                       ` Abdellatif El Khlifi
  2023-07-07 17:35                                                                                                                         ` Simon Glass
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 08/11] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                                                                                                         ` (3 subsequent siblings)
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-07 14:44 UTC (permalink / raw)
  To: sjg
  Cc: trini, abdellatif.elkhlifi, ilias.apalodimas, nd, u-boot,
	Jens Wiklander, Heinrich Schuchardt

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>
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>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove reparenting by making the emulator parent of the FF-A device in the DT
* add invoke_ffa_fn()
* address nits

v11:

* rename ffa_try_discovery() to sandbox_ffa_discover()
* rename sandbox_ffa_query_core_state() to sandbox_query_ffa_emul_state()
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device

v10:

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

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

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

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

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

v1: introduce the sandbox driver

 MAINTAINERS                                   |   3 +-
 arch/sandbox/dts/sandbox.dtsi                 |   9 +
 arch/sandbox/dts/test.dts                     |   8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |  72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        | 121 +++
 configs/sandbox64_defconfig                   |   1 +
 configs/sandbox_defconfig                     |   1 +
 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, 1081 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 ff6a222960..f8948b7635 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..96b5404991 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1820,6 +1820,14 @@
 	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..72ea3d21ab 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -260,3 +260,4 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 1ec44d5b33..8269bec879 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -344,3 +344,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 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


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v14 08/11] arm_ffa: introduce sandbox test cases for UCLASS_FFA
  2023-07-07 14:43                                                                                                                     ` [PATCH v14 00/11] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                         ` (6 preceding siblings ...)
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 07/11] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
@ 2023-07-07 14:44                                                                                                                       ` Abdellatif El Khlifi
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 09/11] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                                                                                                         ` (2 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-07 14:44 UTC (permalink / raw)
  To: sjg
  Cc: trini, abdellatif.elkhlifi, ilias.apalodimas, nd, u-boot,
	Jens Wiklander, Heinrich Schuchardt

Add functional test cases for the FF-A support

These tests rely on the FF-A sandbox emulator and FF-A
sandbox driver which help in inspecting the FF-A communication.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove use of dscvry_info
* drop use of calloc when querying SPs
* address nits

v11:

* drop unmapping test (taken care of by the DM when removing the device)
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT
* address nits

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

v8:

  * update partition_info_get() second argument to be an SP count
  * pass NULL device pointer to the FF-A bus discovery and operations

v7: set the tests to use 64-bit direct messaging

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

v1: introduce sandbox tests

 MAINTAINERS            |   1 +
 doc/arch/arm64.ffa.rst |   1 +
 test/dm/Makefile       |   3 +-
 test/dm/ffa.c          | 261 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 265 insertions(+), 1 deletion(-)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index f8948b7635..4a8b3a5419 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index b7c754fa3d..325fb80346 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -37,6 +37,7 @@ The U-Boot FF-A support provides the following parts:
   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.
+- Sandbox FF-A test cases.
 
 FF-A and SMC specifications
 -------------------------------------------
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 3799b1ae8f..7ed00733c1 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
-# Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -92,6 +92,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..6912666bb4
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <console.h>
+#include <dm.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <asm/sandbox_arm_ffa_priv.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Functional tests for the UCLASS_FFA */
+
+static int check_fwk_version(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	struct ffa_sandbox_data func_data;
+	u32 fwk_version = 0;
+
+	func_data.data0 = &fwk_version;
+	func_data.data0_size = sizeof(fwk_version);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_VERSION, &func_data));
+	ut_asserteq(uc_priv->fwk_version, fwk_version);
+
+	return 0;
+}
+
+static int check_endpoint_id(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_asserteq(0, uc_priv->id);
+
+	return 0;
+}
+
+static int check_rxtxbuf(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assertnonnull(uc_priv->pair.rxbuf);
+	ut_assertnonnull(uc_priv->pair.txbuf);
+
+	return 0;
+}
+
+static int check_features(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assert(uc_priv->pair.rxtx_min_pages == RXTX_4K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_16K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_64K);
+
+	return 0;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+		ut_asserteq(1, rxbuf_mapped);
+		break;
+	case FFA_RXTX_UNMAP:
+		ut_asserteq(0, rxbuf_mapped);
+		break;
+	default:
+		ut_assert(false);
+	}
+
+	return 0;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	ut_asserteq(0, rxbuf_owned);
+
+	return 0;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg;
+	u8 cnt;
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]);
+
+	return 0;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct unit_test_state *uts)
+{
+	struct ffa_partition_desc *descs;
+	u32 count, i, j, valid_sps = 0;
+	struct udevice *dev;
+	struct ffa_sandbox_data func_data;
+	struct ffa_partitions *partitions;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get from the driver the count and information of the SPs matching the UUID */
+	ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, &descs));
+
+	/* Make sure the count is correct */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+
+	/* SPs found , verify the partitions information */
+
+	func_data.data0 = &partitions;
+	func_data.data0_size = sizeof(struct ffa_partitions *);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_PARTITION_INFO_GET, &func_data));
+
+	for (i = 0; i < count ; i++) {
+		for (j = 0;
+		     j < partitions->count;
+		     j++) {
+			if (descs[i].info.id ==
+			   partitions->descs[j].info.id) {
+				valid_sps++;
+				ut_asserteq_mem(&descs[i],
+						&partitions->descs[j],
+						sizeof(struct ffa_partition_desc));
+				/* Send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(descs[i].info.id, uts);
+			}
+		}
+	}
+
+	/* Verify expected partitions found in the emulated secure world */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, valid_sps);
+
+	return 0;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	struct ffa_sandbox_data func_data;
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	struct udevice *dev;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Test FFA_VERSION */
+	check_fwk_version(uc_priv, uts);
+
+	/* Test FFA_ID_GET */
+	check_endpoint_id(uc_priv, uts);
+
+	/* Test FFA_FEATURES */
+	check_features(uc_priv, uts);
+
+	/*  Test RX/TX buffers */
+	check_rxtxbuf(uc_priv, uts);
+
+	/* Test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	sandbox_query_ffa_emul_state(FFA_RXTX_MAP, &func_data);
+	check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc1_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data);
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc2_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data));
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg;
+	int ret;
+	u32 count;
+	u16 part_id = 0;
+	struct udevice *dev;
+	struct ffa_partition_desc *descs = NULL;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Query partitions count using  invalid arguments */
+	ret = ffa_partition_info_get(dev, NULL, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, NULL);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID  string */
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid_str, &count, &descs);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, &descs);
+	ut_asserteq(0, count);
+
+	/* Query partitions data using a valid UUID */
+	count = 0;
+	ut_assertok(ffa_partition_info_get(dev, valid_svc_uuid, &count, &descs));
+	/* Make sure partitions are detected */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+	ut_assertnonnull(descs);
+
+	/* Send data to an invalid partition */
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Send data to a valid partition */
+	part_id = uc_priv->partitions.descs[0].info.id;
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v14 09/11] arm_ffa: introduce armffa command Sandbox test
  2023-07-07 14:43                                                                                                                     ` [PATCH v14 00/11] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                         ` (7 preceding siblings ...)
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 08/11] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-07-07 14:44                                                                                                                       ` Abdellatif El Khlifi
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 10/11] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 11/11] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-07 14:44 UTC (permalink / raw)
  To: sjg
  Cc: trini, abdellatif.elkhlifi, ilias.apalodimas, nd, u-boot, Jens Wiklander

Add Sandbox test for the armffa command

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v12:

* address nits

v10:

* replace CMD_RET_SUCCESS with 0
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT

v9: align the test with FF-A discovery through DM

v4: drop use of helper APIs

v1: introduce armffa command sandbox test

 MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4a8b3a5419..30d1b87149 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index a3cf983739..6e3d7e919e 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -24,6 +25,7 @@ obj-$(CONFIG_CMD_SEAMA) += seama.o
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_CMD_READ) += rw.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o
 endif
 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
 obj-$(CONFIG_CMD_WGET) += wget.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..9a44a397e8
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * 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 <string.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	/* armffa ping <ID> */
+	ut_assertok(run_commandf("armffa ping 0x%x", SANDBOX_SP1_ID));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return 0;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v14 10/11] arm_ffa: efi: introduce FF-A MM communication
  2023-07-07 14:43                                                                                                                     ` [PATCH v14 00/11] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                         ` (8 preceding siblings ...)
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 09/11] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2023-07-07 14:44                                                                                                                       ` Abdellatif El Khlifi
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 11/11] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-07 14:44 UTC (permalink / raw)
  To: sjg
  Cc: trini, abdellatif.elkhlifi, ilias.apalodimas, nd, u-boot,
	Gowtham Suresh Kumar, Jens Wiklander

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

MM communication protocol supports FF-A 64-bit direct messaging.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v14:

Ilias:

* drop truncating var_payload->size when using FF-A
* map the MM SP return codes to errnos

v13:

* remove FF-A and Optee ifdefs

v12:

* drop use of calloc when querying SPs
* address nits

v11:

* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* addressing nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* addressing nits

v9: align how FF-A is used with FF-A discovery through DM

v8:

* isolate the compilation choices between FF-A and OP-TEE
* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make mm_sp_svc_uuid static
* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
* improve use of unmap_sysmem() in ffa_mm_communicate()

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

 include/mm_communication.h        |  13 ++
 lib/efi_loader/Kconfig            |  16 +-
 lib/efi_loader/efi_variable_tee.c | 272 +++++++++++++++++++++++++++++-
 3 files changed, 294 insertions(+), 7 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..f17847583b 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,9 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *    Authors:
+ *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +16,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
@@ -248,4 +254,11 @@ struct smm_variable_var_check_property {
 	u16                       name[];
 };
 
+/* supported MM transports */
+enum mm_comms_select {
+	MM_COMMS_UNDEFINED,
+	MM_COMMS_FFA,
+	MM_COMMS_OPTEE
+};
+
 #endif /* _MM_COMMUNICATION_H_ */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c5835e6ef6..cb26e110fd 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,25 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	select ARM_FFA_TRANSPORT
+	select TEE
+	select OPTEE
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..aef75cb42b 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,17 +4,49 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  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 <cpu_func.h>
+#include <dm.h>
 #include <efi.h>
 #include <efi_api.h>
 #include <efi_loader.h>
 #include <efi_variable.h>
-#include <tee.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <mm_communication.h>
+#include <tee.h>
 
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_SIZE 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_OFFSET
+#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_OFFSET 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h"
+#define FFA_SHARED_MM_BUFFER_ADDR 0
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+#define MM_NOT_SUPPORTED (-1)
+#define MM_INVALID_PARAMETER (-2)
+#define MM_DENIED (-3)
+#define MM_NO_MEMORY (-5)
+
+static const char *mm_sp_svc_uuid = MM_SP_UUID;
+static u16 mm_sp_id;
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -145,16 +177,241 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 }
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notify the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
+		return ret;
+	}
+
+	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
+
+	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
+	if (ret)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	switch (sp_event_ret) {
+	case MM_SUCCESS:
+		ret = 0;
+		break;
+	case MM_NOT_SUPPORTED:
+		ret = -EINVAL;
+		break;
+	case MM_INVALID_PARAMETER:
+		ret = -EPERM;
+		break;
+	case MM_DENIED:
+		ret = -EACCES;
+		break;
+	case MM_NO_MEMORY:
+		ret = -EBUSY;
+		break;
+	default:
+		ret = -EACCES;
+	}
+
+	return ret;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
+		return ret;
+	}
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, &descs);
+	if (ret) {
+		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
+		return ret;
+	}
+
+	/* MM SPs found , use the first one */
+
+	mm_sp_id = descs[0].info.id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	return 0;
+}
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	efi_status_t efi_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()) {
+		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+
+	switch (ffa_ret) {
+	case 0: {
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		efi_ret = EFI_SUCCESS;
+		break;
+	}
+	case -EINVAL:
+		efi_ret = EFI_DEVICE_ERROR;
+		break;
+	case -EPERM:
+		efi_ret = EFI_INVALID_PARAMETER;
+		break;
+	case -EACCES:
+		efi_ret = EFI_ACCESS_DENIED;
+		break;
+	case -EBUSY:
+		efi_ret = EFI_OUT_OF_RESOURCES;
+		break;
+	default:
+		efi_ret = EFI_ACCESS_DENIED;
+	}
+
+	unmap_sysmem(virt_shared_buf);
+	return efi_ret;
+}
+
+/**
+ * get_mm_comms() - detect the available MM transport
+ *
+ * Make sure the FF-A bus is probed successfully
+ * which means FF-A communication with secure world works and ready
+ * for use.
+ *
+ * If FF-A bus is not ready, use OPTEE comms.
+ *
+ * Return:
+ *
+ * MM_COMMS_FFA or MM_COMMS_OPTEE
+ */
+static enum mm_comms_select get_mm_comms(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, trying Optee comms\n");
+		return MM_COMMS_OPTEE;
+	}
+
+	return MM_COMMS_FFA;
+}
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 {
 	efi_status_t ret;
+	enum mm_comms_select mm_comms;
 	struct efi_mm_communicate_header *mm_hdr;
 	struct smm_variable_communicate_header *var_hdr;
 
@@ -162,7 +419,12 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+	mm_comms = get_mm_comms();
+	if (mm_comms == MM_COMMS_FFA)
+		ret = ffa_mm_communicate(comm_buf, dsize);
+	else
+		ret = optee_mm_communicate(comm_buf, dsize);
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -697,7 +959,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v14 11/11] arm_ffa: efi: corstone1000: enable MM communication
  2023-07-07 14:43                                                                                                                     ` [PATCH v14 00/11] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                         ` (9 preceding siblings ...)
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 10/11] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-07-07 14:44                                                                                                                       ` Abdellatif El Khlifi
  2023-07-07 17:35                                                                                                                         ` Simon Glass
  10 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-07 14:44 UTC (permalink / raw)
  To: sjg
  Cc: trini, abdellatif.elkhlifi, ilias.apalodimas, nd, u-boot, Jens Wiklander

turn on EFI MM communication

On corstone1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

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>

---

Changelog:
===============

v13:

* remove FF-A config in the defconfig
   (because it's enabled automatically by CONFIG_EFI_MM_COMM_TEE)

v9:

* update copyright string

v8:

* drop OP-TEE configs from Corstone-1000 defconfig

v7:

* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
  FFA_SHARED_MM_BUFFER_OFFSET
* update FFA_SHARED_MM_BUFFER_ADDR value

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

 configs/corstone1000_defconfig |  1 +
 include/configs/corstone1000.h | 15 +++++++++++++--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index a8a79fd105..b57e2322c4 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -65,3 +65,4 @@ CONFIG_EFI_CAPSULE_ON_DISK=y
 CONFIG_EFI_IGNORE_OSINDICATIONS=y
 CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
index 3347c11792..4ef1f05e40 100644
--- a/include/configs/corstone1000.h
+++ b/include/configs/corstone1000.h
@@ -1,9 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * (C) Copyright 2022 ARM Limited
  * (C) Copyright 2022 Linaro
  * Rui Miguel Silva <rui.silva@linaro.org>
- * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  *
  * Configuration for Corstone1000. Parts were derived from other ARM
  * configurations.
@@ -14,6 +16,15 @@
 
 #include <linux/sizes.h>
 
+#define FFA_SHARED_MM_BUFFER_SIZE	SZ_4K /* 4 KB */
+
+/*
+ * shared buffer physical address used for communication between
+ * u-boot and the MM SP
+ */
+#define FFA_SHARED_MM_BUFFER_ADDR	0x02000000UL
+#define FFA_SHARED_MM_BUFFER_OFFSET	0
+
 #define V2M_BASE		0x80000000
 
 #define CFG_PL011_CLOCK	50000000
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v14 05/11] log: select physical address formatting in a generic way
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 05/11] log: select physical address formatting in a generic way Abdellatif El Khlifi
@ 2023-07-07 17:34                                                                                                                         ` Simon Glass
  2023-07-10 12:14                                                                                                                           ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-07-07 17:34 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: trini, ilias.apalodimas, nd, u-boot

Hi Abdellatif,

On Fri, 7 Jul 2023 at 15:44, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> sets the log formatting according to the platform (64-bit vs 32-bit)
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Cc: Simon Glass <sjg@chromium.org>
> ---
>  include/log.h | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/include/log.h b/include/log.h
> index 3bab40b617..689cef905b 100644
> --- a/include/log.h
> +++ b/include/log.h
> @@ -686,4 +686,12 @@ static inline int log_get_default_format(void)
>                (IS_ENABLED(CONFIG_LOGF_FUNC) ? BIT(LOGF_FUNC) : 0);
>  }
>
> +/* Select the right physical address formatting according to the platform */
> +#ifdef CONFIG_PHYS_64BIT
> +#define PhysAddrLength "ll"
> +#else
> +#define PhysAddrLength ""

Shouldn't this be "l" ? We normally use ulong for addresses.

> +#endif
> +#define PHYS_ADDR_LN "%" PhysAddrLength "x"
> +#define PHYS_ADDR_LNU "%" PhysAddrLength "u"
>  #endif
> --
> 2.25.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v14 07/11] arm_ffa: introduce sandbox FF-A support
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 07/11] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
@ 2023-07-07 17:35                                                                                                                         ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-07-07 17:35 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: trini, ilias.apalodimas, nd, u-boot, Jens Wiklander, Heinrich Schuchardt

Hi Abdellatif,

On Fri, 7 Jul 2023 at 15:44, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> 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>
> 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>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
>
> ---
>
> Changelog:
> ===============
>
> v12:
>
> * remove reparenting by making the emulator parent of the FF-A device in the DT
> * add invoke_ffa_fn()
> * address nits
>
> v11:
>
> * rename ffa_try_discovery() to sandbox_ffa_discover()
> * rename sandbox_ffa_query_core_state() to sandbox_query_ffa_emul_state()
> * store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
> * set the emulator as parent of the sandbox FF-A device
>
> v10:
>
> * split the FF-A sandbox support into an emulator and a driver
> * read FFA_VERSION and FFA_PARTITION_INFO_GET state using
>    sandbox_ffa_query_core_state()
> * drop CONFIG_SANDBOX_FFA config
> * address nits
>
> v9: align FF-A sandbox driver with FF-A discovery through DM
>
> v8: update ffa_bus_prvdata_get() to return a pointer rather than
>     a pointer address
>
> v7: state that sandbox driver supports only 64-bit direct messaging
>
> v4: align sandbox driver with the new FF-A driver interfaces
>     and new way of error handling
>
> v1: introduce the sandbox driver
>
>  MAINTAINERS                                   |   3 +-
>  arch/sandbox/dts/sandbox.dtsi                 |   9 +
>  arch/sandbox/dts/test.dts                     |   8 +
>  arch/sandbox/include/asm/sandbox_arm_ffa.h    |  72 ++
>  .../include/asm/sandbox_arm_ffa_priv.h        | 121 +++
>  configs/sandbox64_defconfig                   |   1 +
>  configs/sandbox_defconfig                     |   1 +
>  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, 1081 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

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v14 11/11] arm_ffa: efi: corstone1000: enable MM communication
  2023-07-07 14:44                                                                                                                       ` [PATCH v14 11/11] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
@ 2023-07-07 17:35                                                                                                                         ` Simon Glass
  2023-07-07 17:44                                                                                                                           ` Tom Rini
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-07-07 17:35 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: trini, ilias.apalodimas, nd, u-boot, Jens Wiklander

Hi Abdellatif,

On Fri, 7 Jul 2023 at 15:44, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> turn on EFI MM communication
>
> On corstone1000 platform MM communication between u-boot
> and the secure world (Optee) is done using the FF-A bus.
>
> 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>
>
> ---
>
> Changelog:
> ===============
>
> v13:
>
> * remove FF-A config in the defconfig
>    (because it's enabled automatically by CONFIG_EFI_MM_COMM_TEE)
>
> v9:
>
> * update copyright string
>
> v8:
>
> * drop OP-TEE configs from Corstone-1000 defconfig
>
> v7:
>
> * improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
>   FFA_SHARED_MM_BUFFER_OFFSET
> * update FFA_SHARED_MM_BUFFER_ADDR value
>
> v6:
>
> * corstone-1000: enable optee driver
> * corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig
>
> v4:
>
> * corstone-1000: turn on EFI MM communication
>
>  configs/corstone1000_defconfig |  1 +
>  include/configs/corstone1000.h | 15 +++++++++++++--
>  2 files changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
> index a8a79fd105..b57e2322c4 100644
> --- a/configs/corstone1000_defconfig
> +++ b/configs/corstone1000_defconfig
> @@ -65,3 +65,4 @@ CONFIG_EFI_CAPSULE_ON_DISK=y
>  CONFIG_EFI_IGNORE_OSINDICATIONS=y
>  CONFIG_FWU_MULTI_BANK_UPDATE=y
>  CONFIG_ERRNO_STR=y
> +CONFIG_EFI_MM_COMM_TEE=y
> diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
> index 3347c11792..4ef1f05e40 100644
> --- a/include/configs/corstone1000.h
> +++ b/include/configs/corstone1000.h
> @@ -1,9 +1,11 @@
>  /* SPDX-License-Identifier: GPL-2.0+ */
>  /*
> - * (C) Copyright 2022 ARM Limited
>   * (C) Copyright 2022 Linaro
>   * Rui Miguel Silva <rui.silva@linaro.org>
> - * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *
> + * Authors:
> + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   *
>   * Configuration for Corstone1000. Parts were derived from other ARM
>   * configurations.
> @@ -14,6 +16,15 @@
>
>  #include <linux/sizes.h>
>
> +#define FFA_SHARED_MM_BUFFER_SIZE      SZ_4K /* 4 KB */
> +
> +/*
> + * shared buffer physical address used for communication between
> + * u-boot and the MM SP
> + */
> +#define FFA_SHARED_MM_BUFFER_ADDR      0x02000000UL
> +#define FFA_SHARED_MM_BUFFER_OFFSET    0
> +

These should be in devicetree properties, shouldn't they? We don't
want things in board config.h files anymore.


>  #define V2M_BASE               0x80000000
>
>  #define CFG_PL011_CLOCK        50000000
> --
> 2.25.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v14 11/11] arm_ffa: efi: corstone1000: enable MM communication
  2023-07-07 17:35                                                                                                                         ` Simon Glass
@ 2023-07-07 17:44                                                                                                                           ` Tom Rini
  2023-07-07 18:09                                                                                                                             ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-07-07 17:44 UTC (permalink / raw)
  To: Simon Glass
  Cc: Abdellatif El Khlifi, ilias.apalodimas, nd, u-boot, Jens Wiklander

[-- Attachment #1: Type: text/plain, Size: 3512 bytes --]

On Fri, Jul 07, 2023 at 11:35:05AM -0600, Simon Glass wrote:
> Hi Abdellatif,
> 
> On Fri, 7 Jul 2023 at 15:44, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > turn on EFI MM communication
> >
> > On corstone1000 platform MM communication between u-boot
> > and the secure world (Optee) is done using the FF-A bus.
> >
> > 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>
> >
> > ---
> >
> > Changelog:
> > ===============
> >
> > v13:
> >
> > * remove FF-A config in the defconfig
> >    (because it's enabled automatically by CONFIG_EFI_MM_COMM_TEE)
> >
> > v9:
> >
> > * update copyright string
> >
> > v8:
> >
> > * drop OP-TEE configs from Corstone-1000 defconfig
> >
> > v7:
> >
> > * improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
> >   FFA_SHARED_MM_BUFFER_OFFSET
> > * update FFA_SHARED_MM_BUFFER_ADDR value
> >
> > v6:
> >
> > * corstone-1000: enable optee driver
> > * corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig
> >
> > v4:
> >
> > * corstone-1000: turn on EFI MM communication
> >
> >  configs/corstone1000_defconfig |  1 +
> >  include/configs/corstone1000.h | 15 +++++++++++++--
> >  2 files changed, 14 insertions(+), 2 deletions(-)
> >
> > diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
> > index a8a79fd105..b57e2322c4 100644
> > --- a/configs/corstone1000_defconfig
> > +++ b/configs/corstone1000_defconfig
> > @@ -65,3 +65,4 @@ CONFIG_EFI_CAPSULE_ON_DISK=y
> >  CONFIG_EFI_IGNORE_OSINDICATIONS=y
> >  CONFIG_FWU_MULTI_BANK_UPDATE=y
> >  CONFIG_ERRNO_STR=y
> > +CONFIG_EFI_MM_COMM_TEE=y
> > diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
> > index 3347c11792..4ef1f05e40 100644
> > --- a/include/configs/corstone1000.h
> > +++ b/include/configs/corstone1000.h
> > @@ -1,9 +1,11 @@
> >  /* SPDX-License-Identifier: GPL-2.0+ */
> >  /*
> > - * (C) Copyright 2022 ARM Limited
> >   * (C) Copyright 2022 Linaro
> >   * Rui Miguel Silva <rui.silva@linaro.org>
> > - * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> > + *
> > + * Authors:
> > + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> >   *
> >   * Configuration for Corstone1000. Parts were derived from other ARM
> >   * configurations.
> > @@ -14,6 +16,15 @@
> >
> >  #include <linux/sizes.h>
> >
> > +#define FFA_SHARED_MM_BUFFER_SIZE      SZ_4K /* 4 KB */
> > +
> > +/*
> > + * shared buffer physical address used for communication between
> > + * u-boot and the MM SP
> > + */
> > +#define FFA_SHARED_MM_BUFFER_ADDR      0x02000000UL
> > +#define FFA_SHARED_MM_BUFFER_OFFSET    0
> > +
> 
> These should be in devicetree properties, shouldn't they? We don't
> want things in board config.h files anymore.

Wasn't one of the earlier debates on if the whole thing needs to be in
device tree, or not, because it's a "discoverable bus" and so Linux
wasn't needing one? I don't want to de-rail this series, which I think
we're just about otherwise ready to merge, over that debate again.

As these values have to match up (I assume) with the other side, are
these truly per-board, or SoC dependent?

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v14 11/11] arm_ffa: efi: corstone1000: enable MM communication
  2023-07-07 17:44                                                                                                                           ` Tom Rini
@ 2023-07-07 18:09                                                                                                                             ` Simon Glass
  2023-07-10 15:03                                                                                                                               ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-07-07 18:09 UTC (permalink / raw)
  To: Tom Rini
  Cc: Abdellatif El Khlifi, ilias.apalodimas, nd, u-boot, Jens Wiklander

Hi Tom,

On Fri, 7 Jul 2023 at 11:44, Tom Rini <trini@konsulko.com> wrote:
>
> On Fri, Jul 07, 2023 at 11:35:05AM -0600, Simon Glass wrote:
> > Hi Abdellatif,
> >
> > On Fri, 7 Jul 2023 at 15:44, Abdellatif El Khlifi
> > <abdellatif.elkhlifi@arm.com> wrote:
> > >
> > > turn on EFI MM communication
> > >
> > > On corstone1000 platform MM communication between u-boot
> > > and the secure world (Optee) is done using the FF-A bus.
> > >
> > > 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>
> > >
> > > ---
> > >
> > > Changelog:
> > > ===============
> > >
> > > v13:
> > >
> > > * remove FF-A config in the defconfig
> > >    (because it's enabled automatically by CONFIG_EFI_MM_COMM_TEE)
> > >
> > > v9:
> > >
> > > * update copyright string
> > >
> > > v8:
> > >
> > > * drop OP-TEE configs from Corstone-1000 defconfig
> > >
> > > v7:
> > >
> > > * improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
> > >   FFA_SHARED_MM_BUFFER_OFFSET
> > > * update FFA_SHARED_MM_BUFFER_ADDR value
> > >
> > > v6:
> > >
> > > * corstone-1000: enable optee driver
> > > * corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig
> > >
> > > v4:
> > >
> > > * corstone-1000: turn on EFI MM communication
> > >
> > >  configs/corstone1000_defconfig |  1 +
> > >  include/configs/corstone1000.h | 15 +++++++++++++--
> > >  2 files changed, 14 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
> > > index a8a79fd105..b57e2322c4 100644
> > > --- a/configs/corstone1000_defconfig
> > > +++ b/configs/corstone1000_defconfig
> > > @@ -65,3 +65,4 @@ CONFIG_EFI_CAPSULE_ON_DISK=y
> > >  CONFIG_EFI_IGNORE_OSINDICATIONS=y
> > >  CONFIG_FWU_MULTI_BANK_UPDATE=y
> > >  CONFIG_ERRNO_STR=y
> > > +CONFIG_EFI_MM_COMM_TEE=y
> > > diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h
> > > index 3347c11792..4ef1f05e40 100644
> > > --- a/include/configs/corstone1000.h
> > > +++ b/include/configs/corstone1000.h
> > > @@ -1,9 +1,11 @@
> > >  /* SPDX-License-Identifier: GPL-2.0+ */
> > >  /*
> > > - * (C) Copyright 2022 ARM Limited
> > >   * (C) Copyright 2022 Linaro
> > >   * Rui Miguel Silva <rui.silva@linaro.org>
> > > - * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> > > + *
> > > + * Authors:
> > > + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > >   *
> > >   * Configuration for Corstone1000. Parts were derived from other ARM
> > >   * configurations.
> > > @@ -14,6 +16,15 @@
> > >
> > >  #include <linux/sizes.h>
> > >
> > > +#define FFA_SHARED_MM_BUFFER_SIZE      SZ_4K /* 4 KB */
> > > +
> > > +/*
> > > + * shared buffer physical address used for communication between
> > > + * u-boot and the MM SP
> > > + */
> > > +#define FFA_SHARED_MM_BUFFER_ADDR      0x02000000UL
> > > +#define FFA_SHARED_MM_BUFFER_OFFSET    0
> > > +
> >
> > These should be in devicetree properties, shouldn't they? We don't
> > want things in board config.h files anymore.
>
> Wasn't one of the earlier debates on if the whole thing needs to be in
> device tree, or not, because it's a "discoverable bus" and so Linux
> wasn't needing one? I don't want to de-rail this series, which I think
> we're just about otherwise ready to merge, over that debate again.
>
> As these values have to match up (I assume) with the other side, are
> these truly per-board, or SoC dependent?

Yes let's not derail the series...it has gone on too long already.

But we do need to think about this. Addresses in #defines are not a
great look. It isn't even a CFG.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v14 05/11] log: select physical address formatting in a generic way
  2023-07-07 17:34                                                                                                                         ` Simon Glass
@ 2023-07-10 12:14                                                                                                                           ` Abdellatif El Khlifi
  2023-07-10 14:17                                                                                                                             ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-10 12:14 UTC (permalink / raw)
  To: Simon Glass; +Cc: nd, u-boot

Hi Simon,

On Fri, Jul 07, 2023 at 06:34:14PM +0100, Simon Glass wrote:
> Hi Abdellatif,
> 
> On Fri, 7 Jul 2023 at 15:44, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > sets the log formatting according to the platform (64-bit vs 32-bit)
> >
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Cc: Simon Glass <sjg@chromium.org>
> > ---
> >  include/log.h | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> >
> > diff --git a/include/log.h b/include/log.h
> > index 3bab40b617..689cef905b 100644
> > --- a/include/log.h
> > +++ b/include/log.h
> > @@ -686,4 +686,12 @@ static inline int log_get_default_format(void)
> >                (IS_ENABLED(CONFIG_LOGF_FUNC) ? BIT(LOGF_FUNC) : 0);
> >  }
> >
> > +/* Select the right physical address formatting according to the platform */
> > +#ifdef CONFIG_PHYS_64BIT
> > +#define PhysAddrLength "ll"
> > +#else
> > +#define PhysAddrLength ""
> 
> Shouldn't this be "l" ? We normally use ulong for addresses.
> 

The "ll" is needed by many architectures who declare "phys_addr_t" as "unsigned long long"

Example of architetures doing that: arm, powerpc, ...

Also mips and sandbox use "u64" for "phys_addr_t" , ( "u64" is an "unsigned long long").

Note: When using an "l" for arm, the compiler shows this warning:

cmd/armffa.c:174:18: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘phys_addr_t’ {aka ‘long long unsign
ed int’} [8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat=-Wformat=8;;]
  174 |         log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",
      |                  ^~~~~~~~~~~~~~~~~~
  175 |                  dev->name,
  176 |                  map_to_sysmem(dev),
      |                  ~~~~~~~~~~~~~~~~~~
      |                  |
      |                  phys_addr_t {aka long long unsigned int}

Cheers,
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v14 05/11] log: select physical address formatting in a generic way
  2023-07-10 12:14                                                                                                                           ` Abdellatif El Khlifi
@ 2023-07-10 14:17                                                                                                                             ` Simon Glass
  2023-07-10 14:49                                                                                                                               ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-07-10 14:17 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: nd, u-boot

Hi Abdellatif,

On Mon, 10 Jul 2023 at 06:15, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Hi Simon,
>
> On Fri, Jul 07, 2023 at 06:34:14PM +0100, Simon Glass wrote:
> > Hi Abdellatif,
> >
> > On Fri, 7 Jul 2023 at 15:44, Abdellatif El Khlifi
> > <abdellatif.elkhlifi@arm.com> wrote:
> > >
> > > sets the log formatting according to the platform (64-bit vs 32-bit)
> > >
> > > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > Cc: Simon Glass <sjg@chromium.org>
> > > ---
> > >  include/log.h | 8 ++++++++
> > >  1 file changed, 8 insertions(+)
> > >
> > > diff --git a/include/log.h b/include/log.h
> > > index 3bab40b617..689cef905b 100644
> > > --- a/include/log.h
> > > +++ b/include/log.h
> > > @@ -686,4 +686,12 @@ static inline int log_get_default_format(void)
> > >                (IS_ENABLED(CONFIG_LOGF_FUNC) ? BIT(LOGF_FUNC) : 0);
> > >  }
> > >
> > > +/* Select the right physical address formatting according to the platform */
> > > +#ifdef CONFIG_PHYS_64BIT
> > > +#define PhysAddrLength "ll"
> > > +#else
> > > +#define PhysAddrLength ""
> >
> > Shouldn't this be "l" ? We normally use ulong for addresses.
> >
>
> The "ll" is needed by many architectures who declare "phys_addr_t" as "unsigned long long"
>
> Example of architetures doing that: arm, powerpc, ...
>
> Also mips and sandbox use "u64" for "phys_addr_t" , ( "u64" is an "unsigned long long").

Yes, the ll looks right. I was referring to the "" line.

>
> Note: When using an "l" for arm, the compiler shows this warning:
>
> cmd/armffa.c:174:18: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘phys_addr_t’ {aka ‘long long unsign
> ed int’} [8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat=-Wformat=8;;]
>   174 |         log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",
>       |                  ^~~~~~~~~~~~~~~~~~
>   175 |                  dev->name,
>   176 |                  map_to_sysmem(dev),
>       |                  ~~~~~~~~~~~~~~~~~~
>       |                  |
>       |                  phys_addr_t {aka long long unsigned int}

Hmm I was hoping that we could use ll for 64-bit and l for 32-bit and
that this could be a generic header for all archs.

Can we get your series in as is and deal with this separately. I was
intending for this to be a follow-up patch.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v14 05/11] log: select physical address formatting in a generic way
  2023-07-10 14:17                                                                                                                             ` Simon Glass
@ 2023-07-10 14:49                                                                                                                               ` Abdellatif El Khlifi
  2023-07-10 19:45                                                                                                                                 ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-10 14:49 UTC (permalink / raw)
  To: Simon Glass; +Cc: nd, u-boot

Hi Simon,

On Mon, Jul 10, 2023 at 08:17:41AM -0600, Simon Glass wrote:
> Hi Abdellatif,
> 
> On Mon, 10 Jul 2023 at 06:15, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > Hi Simon,
> >
> > On Fri, Jul 07, 2023 at 06:34:14PM +0100, Simon Glass wrote:
> > > Hi Abdellatif,
> > >
> > > On Fri, 7 Jul 2023 at 15:44, Abdellatif El Khlifi
> > > <abdellatif.elkhlifi@arm.com> wrote:
> > > >
> > > > sets the log formatting according to the platform (64-bit vs 32-bit)
> > > >
> > > > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > Cc: Simon Glass <sjg@chromium.org>
> > > > ---
> > > >  include/log.h | 8 ++++++++
> > > >  1 file changed, 8 insertions(+)
> > > >
> > > > diff --git a/include/log.h b/include/log.h
> > > > index 3bab40b617..689cef905b 100644
> > > > --- a/include/log.h
> > > > +++ b/include/log.h
> > > > @@ -686,4 +686,12 @@ static inline int log_get_default_format(void)
> > > >                (IS_ENABLED(CONFIG_LOGF_FUNC) ? BIT(LOGF_FUNC) : 0);
> > > >  }
> > > >
> > > > +/* Select the right physical address formatting according to the platform */
> > > > +#ifdef CONFIG_PHYS_64BIT
> > > > +#define PhysAddrLength "ll"
> > > > +#else
> > > > +#define PhysAddrLength ""
> > >
> > > Shouldn't this be "l" ? We normally use ulong for addresses.
> > >
> >
> > The "ll" is needed by many architectures who declare "phys_addr_t" as "unsigned long long"
> >
> > Example of architetures doing that: arm, powerpc, ...
> >
> > Also mips and sandbox use "u64" for "phys_addr_t" , ( "u64" is an "unsigned long long").
> 
> Yes, the ll looks right. I was referring to the "" line.
> 
> >
> > Note: When using an "l" for arm, the compiler shows this warning:
> >
> > cmd/armffa.c:174:18: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘phys_addr_t’ {aka ‘long long unsign
> > ed int’} [8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat=-Wformat=8;;]
> >   174 |         log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",
> >       |                  ^~~~~~~~~~~~~~~~~~
> >   175 |                  dev->name,
> >   176 |                  map_to_sysmem(dev),
> >       |                  ~~~~~~~~~~~~~~~~~~
> >       |                  |
> >       |                  phys_addr_t {aka long long unsigned int}
> 
> Hmm I was hoping that we could use ll for 64-bit and l for 32-bit and
> that this could be a generic header for all archs.

The "" was there for 32-bit architecures (e.g: sandbox, mips) who declare "phys_addr_t" as u32 or "unsigned int"

For example, when using sandbox  with "l" in place of "", there is a compiler warning:

cmd/armffa.c:174:11: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 8 has type ‘phys_addr_t’ {aka ‘unsigned int’} -
Wformat=]
  174 |  log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",

> 
> Can we get your series in as is and deal with this separately. I was
> intending for this to be a follow-up patch.

Sounds good to me. I'll move this commit out of the FF-A patchset and define PHYS_ADDR_LN in armffa.c to be used only there.

Is that ok ?

Cheers,
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v14 11/11] arm_ffa: efi: corstone1000: enable MM communication
  2023-07-07 18:09                                                                                                                             ` Simon Glass
@ 2023-07-10 15:03                                                                                                                               ` Abdellatif El Khlifi
  2023-07-10 16:18                                                                                                                                 ` Tom Rini
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-10 15:03 UTC (permalink / raw)
  To: Simon Glass, trini; +Cc: nd, u-boot

Hi Simon, Tom,

> > > >  #include <linux/sizes.h>
> > > >
> > > > +#define FFA_SHARED_MM_BUFFER_SIZE      SZ_4K /* 4 KB */
> > > > +
> > > > +/*
> > > > + * shared buffer physical address used for communication between
> > > > + * u-boot and the MM SP
> > > > + */
> > > > +#define FFA_SHARED_MM_BUFFER_ADDR      0x02000000UL
> > > > +#define FFA_SHARED_MM_BUFFER_OFFSET    0
> > > > +
> > >
> > > These should be in devicetree properties, shouldn't they? We don't
> > > want things in board config.h files anymore.
> >
> > Wasn't one of the earlier debates on if the whole thing needs to be in
> > device tree, or not, because it's a "discoverable bus" and so Linux
> > wasn't needing one? I don't want to de-rail this series, which I think
> > we're just about otherwise ready to merge, over that debate again.
> >
> > As these values have to match up (I assume) with the other side, are
> > these truly per-board, or SoC dependent?
> 
> Yes let's not derail the series...it has gone on too long already.
> 
> But we do need to think about this. Addresses in #defines are not a
> great look. It isn't even a CFG.
> 

I think replacing the FFA_SHARED_MM_BUFFER_* defines with
a config makes sense.

In v15 I'll add these as configs if you think guys it's appropriate:

FFA_SHARED_MM_BUFFER_SIZE
FFA_SHARED_MM_BUFFER_ADDR
FFA_SHARED_MM_BUFFER_OFFSET

Cheers
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v14 11/11] arm_ffa: efi: corstone1000: enable MM communication
  2023-07-10 15:03                                                                                                                               ` Abdellatif El Khlifi
@ 2023-07-10 16:18                                                                                                                                 ` Tom Rini
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-07-10 16:18 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: Simon Glass, nd, u-boot

[-- Attachment #1: Type: text/plain, Size: 1574 bytes --]

On Mon, Jul 10, 2023 at 04:03:22PM +0100, Abdellatif El Khlifi wrote:
> Hi Simon, Tom,
> 
> > > > >  #include <linux/sizes.h>
> > > > >
> > > > > +#define FFA_SHARED_MM_BUFFER_SIZE      SZ_4K /* 4 KB */
> > > > > +
> > > > > +/*
> > > > > + * shared buffer physical address used for communication between
> > > > > + * u-boot and the MM SP
> > > > > + */
> > > > > +#define FFA_SHARED_MM_BUFFER_ADDR      0x02000000UL
> > > > > +#define FFA_SHARED_MM_BUFFER_OFFSET    0
> > > > > +
> > > >
> > > > These should be in devicetree properties, shouldn't they? We don't
> > > > want things in board config.h files anymore.
> > >
> > > Wasn't one of the earlier debates on if the whole thing needs to be in
> > > device tree, or not, because it's a "discoverable bus" and so Linux
> > > wasn't needing one? I don't want to de-rail this series, which I think
> > > we're just about otherwise ready to merge, over that debate again.
> > >
> > > As these values have to match up (I assume) with the other side, are
> > > these truly per-board, or SoC dependent?
> > 
> > Yes let's not derail the series...it has gone on too long already.
> > 
> > But we do need to think about this. Addresses in #defines are not a
> > great look. It isn't even a CFG.
> > 
> 
> I think replacing the FFA_SHARED_MM_BUFFER_* defines with
> a config makes sense.
> 
> In v15 I'll add these as configs if you think guys it's appropriate:
> 
> FFA_SHARED_MM_BUFFER_SIZE
> FFA_SHARED_MM_BUFFER_ADDR
> FFA_SHARED_MM_BUFFER_OFFSET

Sounds good, thanks!

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v14 05/11] log: select physical address formatting in a generic way
  2023-07-10 14:49                                                                                                                               ` Abdellatif El Khlifi
@ 2023-07-10 19:45                                                                                                                                 ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-07-10 19:45 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: nd, u-boot

Hi Abdellatif,

On Mon, 10 Jul 2023 at 08:49, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Hi Simon,
>
> On Mon, Jul 10, 2023 at 08:17:41AM -0600, Simon Glass wrote:
> > Hi Abdellatif,
> >
> > On Mon, 10 Jul 2023 at 06:15, Abdellatif El Khlifi
> > <abdellatif.elkhlifi@arm.com> wrote:
> > >
> > > Hi Simon,
> > >
> > > On Fri, Jul 07, 2023 at 06:34:14PM +0100, Simon Glass wrote:
> > > > Hi Abdellatif,
> > > >
> > > > On Fri, 7 Jul 2023 at 15:44, Abdellatif El Khlifi
> > > > <abdellatif.elkhlifi@arm.com> wrote:
> > > > >
> > > > > sets the log formatting according to the platform (64-bit vs 32-bit)
> > > > >
> > > > > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > > Cc: Simon Glass <sjg@chromium.org>
> > > > > ---
> > > > >  include/log.h | 8 ++++++++
> > > > >  1 file changed, 8 insertions(+)
> > > > >
> > > > > diff --git a/include/log.h b/include/log.h
> > > > > index 3bab40b617..689cef905b 100644
> > > > > --- a/include/log.h
> > > > > +++ b/include/log.h
> > > > > @@ -686,4 +686,12 @@ static inline int log_get_default_format(void)
> > > > >                (IS_ENABLED(CONFIG_LOGF_FUNC) ? BIT(LOGF_FUNC) : 0);
> > > > >  }
> > > > >
> > > > > +/* Select the right physical address formatting according to the platform */
> > > > > +#ifdef CONFIG_PHYS_64BIT
> > > > > +#define PhysAddrLength "ll"
> > > > > +#else
> > > > > +#define PhysAddrLength ""
> > > >
> > > > Shouldn't this be "l" ? We normally use ulong for addresses.
> > > >
> > >
> > > The "ll" is needed by many architectures who declare "phys_addr_t" as "unsigned long long"
> > >
> > > Example of architetures doing that: arm, powerpc, ...
> > >
> > > Also mips and sandbox use "u64" for "phys_addr_t" , ( "u64" is an "unsigned long long").
> >
> > Yes, the ll looks right. I was referring to the "" line.
> >
> > >
> > > Note: When using an "l" for arm, the compiler shows this warning:
> > >
> > > cmd/armffa.c:174:18: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘phys_addr_t’ {aka ‘long long unsign
> > > ed int’} [8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat=-Wformat=8;;]
> > >   174 |         log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",
> > >       |                  ^~~~~~~~~~~~~~~~~~
> > >   175 |                  dev->name,
> > >   176 |                  map_to_sysmem(dev),
> > >       |                  ~~~~~~~~~~~~~~~~~~
> > >       |                  |
> > >       |                  phys_addr_t {aka long long unsigned int}
> >
> > Hmm I was hoping that we could use ll for 64-bit and l for 32-bit and
> > that this could be a generic header for all archs.
>
> The "" was there for 32-bit architecures (e.g: sandbox, mips) who declare "phys_addr_t" as u32 or "unsigned int"
>
> For example, when using sandbox  with "l" in place of "", there is a compiler warning:
>
> cmd/armffa.c:174:11: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 8 has type ‘phys_addr_t’ {aka ‘unsigned int’} -
> Wformat=]
>   174 |  log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",
>
> >
> > Can we get your series in as is and deal with this separately. I was
> > intending for this to be a follow-up patch.
>
> Sounds good to me. I'll move this commit out of the FF-A patchset and define PHYS_ADDR_LN in armffa.c to be used only there.
>
> Is that ok ?

It's fine with me.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v15 00/10] introduce Arm FF-A support
  2023-07-10 16:18                                                                                                                                 ` Tom Rini
@ 2023-07-13 13:28                                                                                                                                   ` Abdellatif El Khlifi
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                                                                                                                       ` (12 more replies)
  0 siblings, 13 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-13 13:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, sjg, u-boot, ilias.apalodimas,
	Rob Herring, Jens Wiklander, Achin Gupta, Drew Reed,
	Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].

FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
communicate with each other. A partition could be a VM in the Normal or Secure world, an
application in S-EL0, or a Trusted OS in S-EL1.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

   => dm tree

    Class     Index  Probed  Driver                Name
   -----------------------------------------------------------
   ...
    firmware      0  [ + ]   psci                      |-- psci
    ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
   ...

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

This implementation of the specification provides support for Aarch64.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

    - Discover the presence of secure partitions (SPs) of interest
    - Access an SP's service through communication protocols
      (e.g: EFI MM communication protocol)

The FF-A support provides the following features:

    - Being generic by design and can be used by any Arm 64-bit platform
    - FF-A support can be compiled and used without EFI
    - Support for SMCCCv1.2 x0-x17 registers
    - Support for SMC32 calling convention
    - Support for 32-bit and 64-bit FF-A direct messaging
    - Support for FF-A MM communication (compatible with EFI boot time)
    - Enabling FF-A and MM communication in Corstone1000 platform as a use case
    - 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.
    - Sandbox FF-A test cases.
    - A new command called armffa is provided as an example of how to access the
      FF-A bus

For more details about the FF-A support please refer to [B] and refer to [C] for
how to use the armffa command.

Please find at [D] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of changes:
===========================

v15:

Simon:

* drop commit "log: select physical address formatting in a generic way",
   this will be sent as a follow-up commit independently from this patchset
* armffa.c : integrate PHYS_ADDR_LN
* replace FFA_SHARED_MM_BUFFER_* defines with configs

v14: [14]

Simon:

    * add to log.h a generic physical address formatting

Ilias:

    * armffa command: in do_ffa_ping() reject the SP ID if it's 0
    * MM comms: drop truncating var_payload->size when using FF-A
    * MM comms: map the MM SP return codes to errnos
    * address nits

v13: [13]

Ilias:
    * remove FF-A and Optee ifdefs in efi_variable_tee.c
    * doc minor change: specify in the readme that the user
       should call ffa_rxtx_unmap() driver operation to unmap
       the RX/TX buffers on demand.

v12: [12]

* remove the global variable (dscvry_info), use uc_priv instead
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* remove reparenting by making the sandbox emulator parent of the FF-A device in the DT
* improve argument checks for the armffa command
* address nits

v11: [11]

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* use U_BOOT_CMD_WITH_SUBCMDS for armffa command
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device
* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* use ut_asserteq_mem() in uuid_str_to_le_bin test case
* address nits

v10: [10]

* provide the FF-A driver operations through the Uclass (arm-ffa-uclass.c)
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c renamed from core.c)
* split the FF-A sandbox support into an emulator (ffa-emul-uclass.c) and a driver (sandbox_ffa.c)
* use the FF-A driver Uclass operations by clients (armffa command, tests, MM comms)
* use uclass_first_device to search and probe the FF-A device (whether it is on Arm or on sandbox)
* address nits

v9: [9]

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
* align FF-A sandbox driver with FF-A discovery through DM
* use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
* add documentation for the armffa command: doc/usage/cmd/armffa.rst
* introduce testcase for uuid_str_to_le_bin

v8: [8]

* pass the FF-A bus device to the bus operations
* isolate the compilation choices between FF-A and OP-TEE
* drop OP-TEE configs from Corstone-1000 defconfig
* make ffa_get_partitions_info() second argument to be an SP count in both
  modes

v7: [7]

* add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v6: [6]

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

List of previous patches:

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
[7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
[8]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
[9]: https://lore.kernel.org/all/20230310141016.137986-1-abdellatif.elkhlifi@arm.com/
[10]: https://lore.kernel.org/all/20230328161157.219375-1-abdellatif.elkhlifi@arm.com/
[11]: https://lore.kernel.org/all/20230412094245.44674-1-abdellatif.elkhlifi@arm.com/
[12]: https://lore.kernel.org/all/20230512121044.111574-1-abdellatif.elkhlifi@arm.com/
[13]: https://lore.kernel.org/all/20230616152817.319869-1-abdellatif.elkhlifi@arm.com/
[14]: https://lore.kernel.org/all/20230707144410.228472-1-abdellatif.elkhlifi@arm.com/

More details:

[A]: https://developer.arm.com/documentation/den0077/latest/
[B]: doc/arch/arm64.ffa.rst
[C]: doc/usage/cmd/armffa.rst
[D]: example of boot logs when enabling FF-A

```
   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64

   DRAM:  2 GiB
   Arm FF-A framework discovery
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   ...
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   EFI: MM partition ID 0x8003
   ...
   EFI stub: Booting Linux Kernel...
   ...
   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
   Machine model: ARM Corstone1000 FPGA MPS3 board
```

Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (10):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce uuid_str_to_le_bin function
  lib: uuid: introduce testcase for uuid_str_to_le_bin
  arm_ffa: introduce Arm FF-A support
  arm_ffa: introduce armffa command
  arm_ffa: introduce sandbox FF-A support
  arm_ffa: introduce sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   18 +
 arch/arm/cpu/armv8/smccc-call.S               |   57 +-
 arch/arm/lib/asm-offsets.c                    |   16 +
 arch/sandbox/dts/sandbox.dtsi                 |    9 +
 arch/sandbox/dts/test.dts                     |    8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |   72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        |  121 ++
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    1 +
 cmd/armffa.c                                  |  202 ++++
 configs/corstone1000_defconfig                |    4 +
 configs/sandbox64_defconfig                   |    1 +
 configs/sandbox_defconfig                     |    1 +
 doc/arch/arm64.ffa.rst                        |  261 ++++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox/sandbox.rst                  |    1 +
 doc/usage/cmd/armffa.rst                      |   93 ++
 doc/usage/index.rst                           |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   42 +
 drivers/firmware/arm-ffa/Makefile             |   16 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 drivers/firmware/arm-ffa/ffa-emul-uclass.c    |  720 +++++++++++
 drivers/firmware/arm-ffa/sandbox_ffa.c        |  110 ++
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/dm/uclass-id.h                        |    7 +
 include/linux/arm-smccc.h                     |   45 +
 include/mm_communication.h                    |   13 +
 include/uuid.h                                |   15 +
 lib/efi_loader/Kconfig                        |   46 +-
 lib/efi_loader/efi_variable_tee.c             |  257 +++-
 lib/uuid.c                                    |   48 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   33 +
 test/dm/Makefile                              |    3 +-
 test/dm/ffa.c                                 |  261 ++++
 test/lib/Makefile                             |    1 +
 test/lib/uuid.c                               |   41 +
 41 files changed, 4158 insertions(+), 9 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 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 doc/usage/cmd/armffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/lib/uuid.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v15 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-07-13 13:28                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
                                                                                                                                                       ` (11 subsequent siblings)
  12 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-13 13:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, sjg, u-boot, ilias.apalodimas, Jens Wiklander

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>

---

Changelog:
===============

v9:

* update the copyright string

v7:

* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

 arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
 arch/arm/lib/asm-offsets.c      | 16 +++++++++
 include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..93f66d3366 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,7 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
- */
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+*/
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
 #include <generated/asm-offsets.h>
@@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 6de0ce9152..181a8ac4c2 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,11 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * 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>
@@ -90,6 +95,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#ifdef CONFIG_ARM64
+	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..f44e9e8f93 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +74,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v15 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-07-13 13:28                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
                                                                                                                                                       ` (10 subsequent siblings)
  12 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-13 13:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, sjg, u-boot, ilias.apalodimas, Jens Wiklander

convert UUID string to little endian binary data

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v9:

* add a full function prototype description in uuid.h

v8:

* use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

 include/uuid.h | 15 +++++++++++++++
 lib/uuid.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..89b93e642b 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,10 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +48,15 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ * Return:
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 96e1af3c8b..45f325d964 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * 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>
@@ -354,6 +358,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16;
+	u32 tmp32;
+	u64 tmp64;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+	memcpy(uuid_bin, &tmp32, 4);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16));
+	memcpy(uuid_bin + 10, &tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v15 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2023-07-13 13:28                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                       ` (9 subsequent siblings)
  12 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-13 13:28 UTC (permalink / raw)
  To: trini; +Cc: abdellatif.elkhlifi, nd, sjg, u-boot, ilias.apalodimas

provide a test case

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>

---

Changelog:
===============

v11:

* use ut_asserteq_mem()

 MAINTAINERS       |  5 +++++
 test/lib/Makefile |  1 +
 test/lib/uuid.c   | 41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)
 create mode 100644 test/lib/uuid.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d724b64673..a1e34ab63a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1634,3 +1634,8 @@ S:	Maintained
 F:	arch/arm/dts/ls1021a-twr-u-boot.dtsi
 F:	drivers/crypto/fsl/
 F:	include/fsl_sec.h
+
+UUID testing
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	test/lib/uuid.c
diff --git a/test/lib/Makefile b/test/lib/Makefile
index e0bd9e04e8..e75a263e6a 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_AES) += test_aes.o
 obj-$(CONFIG_GETOPT) += getopt.o
 obj-$(CONFIG_CRC8) += test_crc8.o
 obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o
+obj-$(CONFIG_LIB_UUID) += uuid.o
 else
 obj-$(CONFIG_SANDBOX) += kconfig_spl.o
 endif
diff --git a/test/lib/uuid.c b/test/lib/uuid.c
new file mode 100644
index 0000000000..e24331a136
--- /dev/null
+++ b/test/lib/uuid.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <uuid.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* test UUID */
+#define TEST_SVC_UUID	"ed32d533-4209-99e6-2d72-cdd998a79cc0"
+
+#define UUID_SIZE 16
+
+/* The UUID binary data (little-endian format) */
+static const u8 ref_uuid_bin[UUID_SIZE] = {
+	0x33, 0xd5, 0x32, 0xed,
+	0x09, 0x42, 0xe6, 0x99,
+	0x72, 0x2d, 0xc0, 0x9c,
+	0xa7, 0x98, 0xd9, 0xcd
+};
+
+static int lib_test_uuid_to_le(struct unit_test_state *uts)
+{
+	const char *uuid_str = TEST_SVC_UUID;
+	u8 ret_uuid_bin[UUID_SIZE] = {0};
+
+	ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin));
+	ut_asserteq_mem(ref_uuid_bin, ret_uuid_bin, UUID_SIZE);
+
+	return 0;
+}
+
+LIB_TEST(lib_test_uuid_to_le, 0);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v15 04/10] arm_ffa: introduce Arm FF-A support
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                       ` (2 preceding siblings ...)
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-07-13 13:28                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                                                                                                                       ` (8 subsequent siblings)
  12 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-13 13:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, sjg, u-boot, ilias.apalodimas,
	Jens Wiklander, Heinrich Schuchardt

Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- ffa_partition_info_get
- ffa_sync_send_receive
- ffa_rxtx_unmap

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 please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v13:

* doc minor change: specify in the readme that the user
   should call ffa_rxtx_unmap() driver operation to unmap
   the RX/TX buffers on demand.

v12:

* remove dscvry_info
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* address nits

v11:

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* pass dev as an argument of arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* add emul field in struct ffa_discovery_info
* address nits

v10:

* provide the driver operations through the Uclass
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c)
* rename core.c to arm-ffa.c
* address nits

v9:

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding

v8:

* make ffa_get_partitions_info() second argument to be an SP count in both
  modes
* update ffa_bus_prvdata_get() to return a pointer rather than a pointer
  address
* remove packing from ffa_partition_info and ffa_send_direct_data structures
* pass the FF-A bus device to the bus operations

v7:

* add support for 32-bit direct messaging
* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* improve the declaration of error handling mapping
* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the U-Boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the U-Boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

 MAINTAINERS                                   |    8 +
 doc/arch/arm64.ffa.rst                        |  238 ++++
 doc/arch/index.rst                            |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   36 +
 drivers/firmware/arm-ffa/Makefile             |    8 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |   14 +
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/dm/uclass-id.h                        |    6 +
 13 files changed, 1941 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h

diff --git a/MAINTAINERS b/MAINTAINERS
index a1e34ab63a..b3a16ed802 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,6 +266,14 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+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>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..4f817f053c
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,238 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Support
+================
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
+communicate with each other. A partition could be a VM in the Normal or Secure world, an
+application in S-EL0, or a Trusted OS in S-EL1.
+
+The U-Boot FF-A support (the bus) implements the interfaces to communicate
+with partitions in the Secure world aka Secure partitions (SPs).
+
+The FF-A support specifically focuses on communicating with SPs that
+isolate portions of EFI runtime services that must run in a protected
+environment which is inaccessible by the Host OS or Hypervisor.
+Examples of such services are set/get variables.
+
+The FF-A support uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+At this stage of development only EFI boot-time services are supported.
+Runtime support will be added in future developments.
+
+The U-Boot FF-A support provides the following parts:
+
+- A Uclass driver providing generic FF-A methods.
+- An Arm FF-A device driver providing Arm-specific methods and reusing the Uclass methods.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the U-Boot FF-A support relies on
+`FF-A v1.0 specification`_ and uses SMC32 calling convention which
+means using the first 32-bit data of the Xn registers.
+
+At this stage we only need the FF-A v1.0 features.
+
+The FF-A support has been tested with OP-TEE which supports SMC32 calling
+convention.
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A support uses 64-bit registers as per `SMC Calling Convention v1.2 specification`_.
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+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.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers.
+Then, an SMC instruction is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-Boot Arm FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs.
+
+FF-A bus discovery on Arm 64-bit platforms
+---------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
+an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
+This discovery mechanism is performed by the PSCI driver.
+
+The PSCI driver comes with a PSCI device tree node which is the root node for all
+architecture features including FF-A bus.
+
+::
+
+   => dm tree
+
+    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.
+
+In case of FF-A, the callback is arm_ffa_is_supported() which tries to discover the
+FF-A framework by querying the FF-A framework version from secure world using
+FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
+mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver
+with the device using device_bind_driver().
+
+At this stage the FF-A bus is registered with the DM and can be interacted with using
+the DM APIs.
+
+Clients are able to probe then use the FF-A bus by calling uclass_first_device().
+Please refer to the armffa command implementation as an example of how to probe
+and interact with the FF-A bus.
+
+When calling uclass_first_device(), the FF-A driver is probed and ends up calling
+ffa_do_probe() provided by the Uclass which does the following:
+
+    - saving the FF-A framework version in uc_priv
+    - querying from secure world the u-boot endpoint ID
+    - querying from secure world the supported features of FFA_RXTX_MAP
+    - mapping the RX/TX buffers
+    - querying from secure world all the partitions information
+
+When one of the above actions fails, probing fails and the driver stays not active
+and can be probed again if needed.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must query the SPs they are looking for
+during EFI boot-time mode using the service UUID.
+
+The RX/TX buffers are only available at EFI boot-time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped before EFI runtime mode starts.
+The driver provides a bus operation for that called ffa_rxtx_unmap().
+
+The user should call ffa_rxtx_unmap() to unmap the RX/TX buffers when required
+(e.g: at efi_exit_boot_services()).
+
+The Linux kernel allocates its own RX/TX buffers. To be able to register these kernel buffers
+with secure world, the U-Boot's RX/TX buffers should be unmapped before EFI runtime starts.
+
+When invoking FF-A direct messaging, clients should specify which ABI protocol
+they want to use (32-bit vs 64-bit). Selecting the protocol means using
+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
+The calling convention between U-Boot and the secure world stays the same: SMC32.
+
+Requirements for user drivers
+-------------------------------------
+
+Users who want to implement their custom FF-A device driver while reusing the FF-A Uclass can do so
+by implementing their own invoke_ffa_fn() in the user driver.
+
+The bus driver layer
+------------------------------
+
+FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c
+
+The following features are provided:
+
+- Support for the 32-bit version of the following ABIs:
+
+    - FFA_VERSION
+    - FFA_ID_GET
+    - FFA_FEATURES
+    - FFA_PARTITION_INFO_GET
+    - FFA_RXTX_UNMAP
+    - FFA_RX_RELEASE
+    - FFA_RUN
+    - FFA_ERROR
+    - FFA_SUCCESS
+    - FFA_INTERRUPT
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Support for the 64-bit version of the following ABIs:
+
+    - FFA_RXTX_MAP
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, FF-A support takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- FF-A support provides driver operations to be used by upper layers:
+
+    - ffa_partition_info_get
+    - ffa_sync_send_receive
+    - ffa_rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+Example of boot logs with FF-A enabled
+--------------------------------------
+
+For example, when using FF-A with Corstone-1000 the logs are as follows:
+
+::
+
+   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64
+
+   DRAM:  2 GiB
+   Arm FF-A framework discovery
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   ...
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   EFI: MM partition ID 0x8003
+   ...
+   EFI stub: Booting Linux Kernel...
+   ...
+   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
+   Machine model: ARM Corstone1000 FPGA MPS3 board
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+
+.. _`FF-A v1.0 specification`: https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e
+.. _`SMC Calling Convention v1.2 specification`: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index b8da4b8c8e..2f916f4026 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Makefile b/drivers/Makefile
index 78dcf62f76..5044f45253 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -115,6 +115,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index eae1c8ddc9..8789b1ea14 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
 	  the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
 	  services if any and reported as supported by the SMCCC firmware.
 
+source "drivers/firmware/arm-ffa/Kconfig"
 source "drivers/firmware/scmi/Kconfig"
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..9200c8028b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select ARM_SMCCC_FEATURES
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
+	  FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
+	  by the PSCI driver.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  The FF-A support on U-Boot  takes care of all the interactions between Normal
+	  world and Secure World.
+
+	  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
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..11b1766285
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,8 @@
+# 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>
+
+obj-y += arm-ffa-uclass.o arm-ffa.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..ffa9d81fa7
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,1065 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	[NOT_SUPPORTED] = -EOPNOTSUPP,
+	[INVALID_PARAMETERS] = -EINVAL,
+	[NO_MEMORY] = -ENOMEM,
+	[BUSY] = -EBUSY,
+	[INTERRUPTED] = -EINTR,
+	[DENIED] = -EACCES,
+	[RETRY] = -EAGAIN,
+	[ABORTED] = -ECANCELED,
+};
+
+static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			[NO_MEMORY] =
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			[BUSY] =
+			"BUSY: RX buffer of the caller is not free",
+			[DENIED] =
+			"DENIED: Callee is not in a state to handle this request",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			[DENIED] =
+			"DENIED: Caller did not have ownership of the RX buffer",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			[NO_MEMORY] =
+			"NO_MEMORY: Not enough memory",
+			[DENIED] =
+			"DENIED: Buffer pair already registered",
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno() - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+static int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* Map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+static int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* Map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	log_err("%s\n", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/* FF-A ABIs implementation (U-Boot side) */
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void __weak invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+}
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	log_info("FF-A driver %d.%d\nFF-A framework %d.%d\n",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) {
+		log_info("FF-A versions are compatible\n");
+
+		if (dev) {
+			uc_priv = dev_get_uclass_priv(dev);
+			if (uc_priv)
+				uc_priv->fwk_version = res.a0;
+		}
+
+		return 0;
+	}
+
+	log_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id() - FFA_ID_GET handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		uc_priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		log_debug("FF-A endpoint ID is %u\n", uc_priv->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt() - set the minimum number of pages in each of the RX/TX buffers
+ * @dev: The FF-A bus device
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * Set the minimum number of pages in each of the RX/TX buffers in uc_priv
+ *
+ * Return:
+ *
+ * rxtx_min_pages field contains the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	switch (prop_field) {
+	case RXTX_4K:
+		uc_priv->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		uc_priv->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		uc_priv->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		log_err("RX/TX buffer size not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features_hdlr() - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_FEATURES FF-A function to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers() - free the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Free the RX/TX buffers
+ */
+static void ffa_free_rxtx_buffers(struct udevice *dev)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Freeing FF-A RX/TX buffers\n");
+
+	if (uc_priv->pair.rxbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+	}
+
+	if (uc_priv->pair.txbuf) {
+		free(uc_priv->pair.txbuf);
+		uc_priv->pair.txbuf = NULL;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers() - allocate the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ * The size of the memory allocated is the minimum allowed.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(struct udevice *dev)
+{
+	u64 bytes;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Using %lu 4KB page(s) for FF-A RX/TX buffers size\n",
+		  uc_priv->pair.rxtx_min_pages);
+
+	bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 * Assumption: Memory allocated with memalign is always physically contiguous
+	 */
+
+	uc_priv->pair.rxbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.rxbuf) {
+		log_err("failure to allocate RX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A RX buffer at virtual address %p\n", uc_priv->pair.rxbuf);
+
+	uc_priv->pair.txbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.txbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+		log_err("failure to allocate the TX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A TX buffer at virtual address %p\n", uc_priv->pair.txbuf);
+
+	/* Make sure the buffers are cleared before use */
+	memset(uc_priv->pair.rxbuf, 0, bytes);
+	memset(uc_priv->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers_hdlr() - FFA_RXTX_MAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_MAP FF-A function to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	ret = ffa_alloc_rxtx_buffers(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 * no need to convert from virtual to physical
+	 */
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = map_to_sysmem(uc_priv->pair.txbuf),
+			.a2 = map_to_sysmem(uc_priv->pair.rxbuf),
+			.a3 = uc_priv->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		log_debug("FF-A RX/TX buffers mapped\n");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers(dev);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_UNMAP FF-A function to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	log_debug("unmapping FF-A RX/TX buffers\n");
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers(dev);
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer_hdlr() - FFA_RX_RELEASE handler function
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_RX_RELEASE FF-A function to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical() - check whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * Used by ffa_read_partitions_info to search for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+static bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+				   const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info() - read queried partition data
+ * @dev: The FF-A bus device
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * Read the partitions information returned by the FFA_PARTITION_INFO_GET and saves it in uc_priv
+ *
+ * Return:
+ *
+ * uc_priv is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(struct udevice *dev, u32 count,
+				    struct ffa_partition_uuid *part_uuid)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	if (!count) {
+		log_err("no partition detected\n");
+		return -ENODATA;
+	}
+
+	log_debug("Reading FF-A partitions data from the RX buffer\n");
+
+	if (!part_uuid) {
+		/* Querying information of all partitions */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			log_err("partitions data size exceeds the RX buffer size:\n");
+			log_err("    sizes in bytes: data %llu , RX buffer %llu\n",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		uc_priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO);
+		if (!uc_priv->partitions.descs) {
+			log_err("cannot  allocate partitions data buffer\n");
+			return -ENOMEM;
+		}
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			uc_priv->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			log_debug("FF-A partition ID %x : info cached\n",
+				  uc_priv->partitions.descs[desc_idx].info.id);
+		}
+
+		uc_priv->partitions.count = count;
+
+		log_debug("%d FF-A partition(s) found and cached\n", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		/*
+		 * Search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/* Search the current ID in the cached partitions */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < uc_priv->partitions.count;
+			     cached_desc_idx++) {
+				/* Save the UUID */
+				if (uc_priv->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					uc_priv->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info() - invoke FFA_PARTITION_INFO_GET and save partitions data
+ * @dev: The FF-A bus device
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * Execute the FFA_PARTITION_INFO_GET to query the partitions data.
+ * Then, call ffa_read_partitions_info to save the data in uc_priv.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid);
+			if (ret) {
+				log_err("failed reading SP(s) data , err (%d)\n", ret);
+				ffa_release_rx_buffer_hdlr(dev);
+				return -EINVAL;
+			}
+		}
+
+		/* Return the SP count (when querying using a UUID) */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer_hdlr(dev);
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET FF-A function to query the partition information
+ * from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * If the partition(s) matching the UUID found, the partition(s) information and the
+ * number are returned.
+ * If no partition matching the UUID is found in the cached area, a new FFA_PARTITION_INFO_GET
+ * call is issued.
+ * If not done yet, the UUID is updated in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	u32 i;
+	struct ffa_partition_uuid part_uuid = {0};
+	struct ffa_priv *uc_priv;
+	struct ffa_partition_desc *rx_descs;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs) {
+		log_err("no partition installed\n");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		log_err("no UUID provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_count) {
+		log_err("no count argument provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_descs) {
+		log_err("no info argument provided\n");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		log_err("invalid UUID\n");
+		return -EINVAL;
+	}
+
+	log_debug("Searching FF-A partitions using the provided UUID\n");
+
+	*sp_count = 0;
+	*sp_descs = uc_priv->pair.rxbuf;
+	rx_descs = *sp_descs;
+
+	/* Search in the cached partitions */
+	for (i = 0; i < uc_priv->partitions.count; i++)
+		if (ffa_uuid_are_identical(&uc_priv->partitions.descs[i].sp_uuid,
+					   &part_uuid)) {
+			log_debug("FF-A partition ID %x matches the provided UUID\n",
+				  uc_priv->partitions.descs[i].info.id);
+
+			(*sp_count)++;
+			*rx_descs++ = uc_priv->partitions.descs[i];
+			}
+
+	if (!(*sp_count)) {
+		int ret;
+
+		log_debug("No FF-A partition found. Querying framework ...\n");
+
+		ret = ffa_query_partitions_info(dev, &part_uuid, sp_count);
+
+		if (!ret) {
+			log_debug("Number of FF-A partition(s) matching the UUID: %d\n", *sp_count);
+
+			if (*sp_count)
+				ret = ffa_get_partitions_info_hdlr(dev, uuid_str, sp_count,
+								   sp_descs);
+			else
+				ret = -ENODATA;
+		}
+
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info() - Query and saves all secure partitions data
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_PARTITION_INFO_GET FF-A function to query from secure world
+ * all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in uc_priv
+ * and we keep the UUID field empty (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * Called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(struct udevice *dev)
+{
+	return ffa_query_partitions_info(dev, NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Implement FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u64 req_mode, resp_mode;
+	struct ffa_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* No partition installed */
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs)
+		return -ENODEV;
+
+	if (is_smc64) {
+		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+	} else {
+		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = req_mode,
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == resp_mode) {
+		/* Message sent with response extract the return data */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/* FF-A driver operations (used by clients for communicating with FF-A)*/
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Driver operation for FFA_PARTITION_INFO_GET.
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->partition_info_get)
+		return -ENOSYS;
+
+	return ops->partition_info_get(dev, uuid_str, sp_count, sp_descs);
+}
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Driver operation for FFA_MSG_SEND_DIRECT_{REQ,RESP}.
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->sync_send_receive)
+		return -ENOSYS;
+
+	return ops->sync_send_receive(dev, dst_part_id, msg, is_smc64);
+}
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * @dev: The FF-A bus device
+ *
+ * Driver operation for FFA_RXTX_UNMAP.
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_rxtx_unmap(struct udevice *dev)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->rxtx_unmap)
+		return -ENOSYS;
+
+	return ops->rxtx_unmap(dev);
+}
+
+/**
+ * ffa_do_probe() - probing FF-A framework
+ * @dev:	the FF-A bus device (arm_ffa)
+ *
+ * Probing is triggered on demand by clients searching for the uclass.
+ * At probe level the following actions are done:
+ *	- saving the FF-A framework version in uc_priv
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in uc_priv.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_do_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_endpoint_id(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_cache_partitions_info(dev);
+	if (ret) {
+		ffa_unmap_rxtx_buffers_hdlr(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+UCLASS_DRIVER(ffa) = {
+	.name			= "ffa",
+	.id			= UCLASS_FFA,
+	.pre_probe		= ffa_do_probe,
+	.pre_remove		= ffa_unmap_rxtx_buffers_hdlr,
+	.per_device_auto	= sizeof(struct ffa_priv)
+};
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
new file mode 100644
index 0000000000..68df75bd9e
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -0,0 +1,104 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <linux/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * 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 low level SMC assembly function
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * arm_ffa_discover() - perform FF-A discovery
+ * @dev: The Arm FF-A bus device (arm_ffa)
+ * 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:
+ *
+ * true on success. Otherwise, false.
+ */
+static bool arm_ffa_discover(struct udevice *dev)
+{
+	int ret;
+
+	log_info("Arm FF-A framework discovery\n");
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/**
+ * arm_ffa_is_supported() - FF-A bus discovery callback
+ * @invoke_fn: legacy SMC invoke function (not used)
+ *
+ * Perform FF-A discovery by calling arm_ffa_discover().
+ * Discovery is performed by querying the FF-A framework version from
+ * secure world using the FFA_VERSION ABI.
+ *
+ * The FF-A driver is registered as an SMCCC feature driver. So, features discovery
+ * callbacks are called by the PSCI driver (PSCI device is the SMCCC features
+ * root device).
+ *
+ * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
+ * So, the legacy SMC invocation is not used.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static bool arm_ffa_is_supported(void (*invoke_fn)(ulong a0, ulong a1,
+						   ulong a2, ulong a3,
+						   ulong a4, ulong a5,
+						   ulong a6, ulong a7,
+						   struct arm_smccc_res *res))
+{
+	return arm_ffa_discover(NULL);
+}
+
+/* Arm FF-A driver operations */
+
+static const struct ffa_bus_ops 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,
+};
+
+/* Registering the FF-A driver as an SMCCC feature driver */
+
+ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
+	.driver_name = FFA_DRV_NAME,
+	.is_supported = arm_ffa_is_supported,
+};
+
+/* Declaring the FF-A driver under UCLASS_FFA */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.flags		= DM_REMOVE_OS_PREPARE,
+	.ops		= &ffa_ops,
+};
diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
new file mode 100644
index 0000000000..4338f9c9b1
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
@@ -0,0 +1,14 @@
+/* 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/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..db9b1be995
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,213 @@
+/* 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 __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
+ * @a1-4:	32-bit words access to the UUID data
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct ffa_send_direct_data {
+	ulong data0; /* w3/x3 */
+	ulong data1; /* w4/x4 */
+	ulong data2; /* w5/x5 */
+	ulong data3; /* w6/x6 */
+	ulong data4; /* w7/x7 */
+};
+
+struct udevice;
+
+/**
+ * struct ffa_bus_ops - Operations for FF-A
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
+				  u32 *sp_count, struct ffa_partition_desc **sp_descs);
+	int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg,
+				 bool is_smc64);
+	int (*rxtx_unmap)(struct udevice *dev);
+};
+
+#define ffa_get_ops(dev)        ((struct ffa_bus_ops *)(dev)->driver->ops)
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ */
+int ffa_rxtx_unmap(struct udevice *dev);
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The arm_ffa bus device
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev);
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The arm_ffa bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+struct ffa_priv;
+
+/**
+ * ffa_set_smc_conduit() - Set the SMC conduit
+ * @dev: The FF-A bus device
+ *
+ * Selects the SMC conduit by setting the FF-A ABI invoke function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_set_smc_conduit(struct udevice *dev);
+
+#endif
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
new file mode 100644
index 0000000000..d564c33c64
--- /dev/null
+++ b/include/arm_ffa_priv.h
@@ -0,0 +1,246 @@
+/* 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 __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <mapmem.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+
+/* This header is exclusively used by the FF-A Uclass and FF-A driver(s) */
+
+/* Arm FF-A driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* The FF-A SMC function definitions */
+
+#if CONFIG_IS_ENABLED(SANDBOX)
+
+/* Providing Arm SMCCC declarations to sandbox */
+
+/**
+ * struct sandbox_smccc_1_2_regs - emulated SMC call arguments or results
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct sandbox_smccc_1_2_regs {
+	ulong a0;
+	ulong a1;
+	ulong a2;
+	ulong a3;
+	ulong a4;
+	ulong a5;
+	ulong a6;
+	ulong a7;
+	ulong a8;
+	ulong a9;
+	ulong a10;
+	ulong a11;
+	ulong a12;
+	ulong a13;
+	ulong a14;
+	ulong a15;
+	ulong a16;
+	ulong a17;
+};
+
+typedef struct sandbox_smccc_1_2_regs ffa_value_t;
+
+#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))
+
+#else
+/* CONFIG_ARM64 */
+#include <linux/arm-smccc.h>
+typedef struct arm_smccc_1_2_regs ffa_value_t;
+#endif
+
+/* Defining the function pointer type for the function executing the FF-A ABIs */
+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)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR                 = 0x60,
+	FFA_SUCCESS               = 0x61,
+	FFA_INTERRUPT             = 0x62,
+	FFA_VERSION               = 0x63,
+	FFA_FEATURES              = 0x64,
+	FFA_RX_RELEASE            = 0x65,
+	FFA_RXTX_MAP              = 0x66,
+	FFA_RXTX_UNMAP            = 0x67,
+	FFA_PARTITION_INFO_GET    = 0x68,
+	FFA_ID_GET                = 0x69,
+	FFA_RUN                   = 0x6d,
+	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
+	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
+
+	/* To be updated when adding new FFA IDs */
+	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
+	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
+};
+
+enum ffa_abi_errcode {
+	NOT_SUPPORTED = 1,
+	INVALID_PARAMETERS,
+	NO_MEMORY,
+	BUSY,
+	INTERRUPTED,
+	DENIED,
+	RETRY,
+	ABORTED,
+	MAX_NUMBER_FFA_ERR
+};
+
+extern int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR];
+
+/* Container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Hosts the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	void *rxbuf; /* Virtual address returned by memalign */
+	void *txbuf; /* Virtual address returned by memalign */
+	size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */
+};
+
+struct ffa_partition_desc;
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * Contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* Virtual address */
+};
+
+/**
+ * struct ffa_priv - the driver private data structure
+ *
+ * @fwk_version:	FF-A framework version
+ * @emul:	FF-A sandbox emulator
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ *
+ * The device private data structure containing all the
+ * data read from secure world.
+ */
+struct ffa_priv {
+	u32 fwk_version;
+	struct udevice *emul;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+};
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev);
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 307ad6931c..3c6af2e3d2 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,11 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -57,6 +62,7 @@ enum uclass_id {
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_EXTCON,		/* External Connector Class */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v15 05/10] arm_ffa: introduce armffa command
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                       ` (3 preceding siblings ...)
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-07-13 13:28                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
                                                                                                                                                       ` (7 subsequent siblings)
  12 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-13 13:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, sjg, u-boot, ilias.apalodimas,
	Jens Wiklander, Heinrich Schuchardt

Provide armffa command showcasing the use of the U-Boot FF-A support

armffa is a command showcasing how to invoke FF-A operations.
This provides a guidance to the client developers on how to
call the FF-A bus interfaces. The command also allows to gather secure
partitions information and ping these  partitions. The command is also
helpful in testing the communication with secure partitions.

For more details please refer to the command documentation [1].

[1]: doc/usage/cmd/armffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v15:

Simon:

* armffa.c : integrate PHYS_ADDR_LN

v14:

Ilias:

* address nits
* in do_ffa_ping() reject the SP ID if it's 0
* use PHYS_ADDR_LN in formatting the physical addresses

v12:

* add subcommands argument checks
* usage documentation: update command return codes
* remove calloc when querying SPs
* address nits

v11:

* use U_BOOT_CMD_WITH_SUBCMDS
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* address nits

v9:

* remove manual FF-A discovery and use DM
* use DM class APIs to probe and interact with the FF-A bus
* add doc/usage/cmd/armffa.rst

v8:

* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* adapt do_ffa_dev_list() following the recent update on
  uclass_first_device/uclass_next_device functions (they return void now)
* set armffa command to use 64-bit direct messaging

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

 MAINTAINERS                      |   2 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   1 +
 cmd/armffa.c                     | 202 +++++++++++++++++++++++++++++++
 doc/arch/arm64.ffa.rst           |   7 ++
 doc/usage/cmd/armffa.rst         |  93 ++++++++++++++
 doc/usage/index.rst              |   1 +
 drivers/firmware/arm-ffa/Kconfig |   1 +
 8 files changed, 317 insertions(+)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/usage/cmd/armffa.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index b3a16ed802..ff6a222960 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,7 +269,9 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+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
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 02e54f1e50..79b4f8367a 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -935,6 +935,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the FF-A support
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index 6c37521b4e..7d20a85a46 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,7 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_2048) += 2048.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..7e6eafc03a
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,202 @@
+// 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 <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+#include <asm/io.h>
+
+/* Select the right physical address formatting according to the platform */
+#ifdef CONFIG_PHYS_64BIT
+#define PhysAddrLength "ll"
+#else
+#define PhysAddrLength ""
+#endif
+#define PHYS_ADDR_LN "%" PhysAddrLength "x"
+
+/**
+ * ffa_get_dev() - Return the FF-A device
+ * @devp:	pointer to the FF-A device
+ *
+ * Search for the FF-A device.
+ *
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_dev(struct udevice **devp)
+{
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, devp);
+	if (ret) {
+		log_err("Cannot find FF-A bus device\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * do_ffa_getpart() - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query a secure partition information. The secure partition UUID is provided
+ * as an argument. The function uses the arm_ffa driver
+ * partition_info_get operation which implements FFA_PARTITION_INFO_GET
+ * ABI to retrieve the data. The input UUID string is expected to be in big
+ * endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	u32 i;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+
+	ret = ffa_partition_info_get(dev, argv[1], &count, &descs);
+	if (ret) {
+		log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	/* SPs found , show the partition information */
+	for (i = 0; i < count ; i++) {
+		log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
+			 descs[i].info.id,
+			 descs[i].info.exec_ctxt,
+			 descs[i].info.properties);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_ffa_ping() - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Send data to a secure partition. The secure partition UUID is provided
+ * as an argument. Use the arm_ffa driver sync_send_receive operation
+ * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	part_id = strtoul(argv[1], NULL, 16);
+	if (!part_id) {
+		log_err("Partition ID can not be 0\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	if (!ret) {
+		u8 cnt;
+
+		log_info("SP response:\n[LSB]\n");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			log_info("%llx\n", ((u64 *)&msg)[cnt]);
+		return CMD_RET_SUCCESS;
+	}
+
+	log_err("Sending direct request error (%d)\n", ret);
+	return CMD_RET_FAILURE;
+}
+
+/**
+ *do_ffa_devlist() - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query the device belonging to the UCLASS_FFA
+ * class.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",
+		 dev->name,
+		 map_to_sysmem(dev),
+		 dev->driver->name,
+		 map_to_sysmem(dev->driver->ops));
+
+	return CMD_RET_SUCCESS;
+}
+
+static char armffa_help_text[] =
+	"getpart <partition UUID>\n"
+	"       - lists the partition(s) info\n"
+	"ping <partition ID>\n"
+	"       - sends a data pattern to the specified partition\n"
+	"devlist\n"
+	"       - displays information about the FF-A device/driver\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
+			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
+			U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping),
+			U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist));
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 4f817f053c..aefd527447 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -205,6 +205,13 @@ The following features are provided:
 
 - FF-A bus can be compiled and used without EFI
 
+The armffa command
+-----------------------------------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke the driver operations.
+
+Please refer the command documentation at :doc:`../usage/cmd/armffa`
+
 Example of boot logs with FF-A enabled
 --------------------------------------
 
diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
new file mode 100644
index 0000000000..3d422686c1
--- /dev/null
+++ b/doc/usage/cmd/armffa.rst
@@ -0,0 +1,93 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+armffa command
+==============
+
+Synopsis
+--------
+
+::
+
+   armffa [sub-command] [arguments]
+
+   sub-commands:
+
+        getpart [partition UUID]
+
+            lists the partition(s) info
+
+        ping [partition ID]
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays information about the FF-A device/driver
+
+Description
+-----------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
+
+The command also allows to gather secure partitions information and ping these  partitions.
+
+The command is also helpful in testing the communication with secure partitions.
+
+Example
+-------
+
+The following examples are run on Corstone-1000 platform.
+
+* ping
+
+::
+
+   corstone1000# armffa ping 0x8003
+   SP response:
+   [LSB]
+   fffffffe
+   0
+   0
+   0
+   0
+
+* ping (failure case)
+
+::
+
+   corstone1000# armffa ping 0
+   Sending direct request error (-22)
+
+* getpart
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
+   Partition: id = 8003 , exec_ctxt 1 , properties 3
+
+* getpart (failure case)
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221
+   INVALID_PARAMETERS: Unrecognized UUID
+   Failure in querying partitions count (error code: -22)
+
+* devlist
+
+::
+
+   corstone1000# armffa devlist
+   device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98
+
+Configuration
+-------------
+
+The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
+
+Return value
+------------
+
+The return value $? is 0 (true) on success, 1 (false) on failure.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 388e59f173..e462de2806 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -22,6 +22,7 @@ Shell commands
 
    cmd/acpi
    cmd/addrmap
+   cmd/armffa
    cmd/askenv
    cmd/base
    cmd/bdinfo
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index 9200c8028b..a7d5392859 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
 	depends on DM && ARM64
 	select ARM_SMCCC
 	select ARM_SMCCC_FEATURES
+	imply CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v15 06/10] arm_ffa: introduce sandbox FF-A support
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                       ` (4 preceding siblings ...)
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-07-13 13:28                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                                                                                                                       ` (6 subsequent siblings)
  12 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-13 13:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, sjg, u-boot, ilias.apalodimas,
	Jens Wiklander, Heinrich Schuchardt

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>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove reparenting by making the emulator parent of the FF-A device in the DT
* add invoke_ffa_fn()
* address nits

v11:

* rename ffa_try_discovery() to sandbox_ffa_discover()
* rename sandbox_ffa_query_core_state() to sandbox_query_ffa_emul_state()
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device

v10:

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

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

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

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

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

v1: introduce the sandbox driver

 MAINTAINERS                                   |   3 +-
 arch/sandbox/dts/sandbox.dtsi                 |   9 +
 arch/sandbox/dts/test.dts                     |   8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |  72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        | 121 +++
 configs/sandbox64_defconfig                   |   1 +
 configs/sandbox_defconfig                     |   1 +
 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, 1081 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 ff6a222960..f8948b7635 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..96b5404991 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1820,6 +1820,14 @@
 	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..72ea3d21ab 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -260,3 +260,4 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 1ec44d5b33..8269bec879 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -344,3 +344,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 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


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v15 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                       ` (5 preceding siblings ...)
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
@ 2023-07-13 13:28                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                                                                                                                       ` (5 subsequent siblings)
  12 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-13 13:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, sjg, u-boot, ilias.apalodimas,
	Jens Wiklander, Heinrich Schuchardt

Add functional test cases for the FF-A support

These tests rely on the FF-A sandbox emulator and FF-A
sandbox driver which help in inspecting the FF-A communication.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove use of dscvry_info
* drop use of calloc when querying SPs
* address nits

v11:

* drop unmapping test (taken care of by the DM when removing the device)
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT
* address nits

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

v8:

  * update partition_info_get() second argument to be an SP count
  * pass NULL device pointer to the FF-A bus discovery and operations

v7: set the tests to use 64-bit direct messaging

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

v1: introduce sandbox tests

 MAINTAINERS            |   1 +
 doc/arch/arm64.ffa.rst |   1 +
 test/dm/Makefile       |   3 +-
 test/dm/ffa.c          | 261 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 265 insertions(+), 1 deletion(-)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index f8948b7635..4a8b3a5419 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index b7c754fa3d..325fb80346 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -37,6 +37,7 @@ The U-Boot FF-A support provides the following parts:
   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.
+- Sandbox FF-A test cases.
 
 FF-A and SMC specifications
 -------------------------------------------
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 3799b1ae8f..7ed00733c1 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
-# Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -92,6 +92,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..6912666bb4
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <console.h>
+#include <dm.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <asm/sandbox_arm_ffa_priv.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Functional tests for the UCLASS_FFA */
+
+static int check_fwk_version(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	struct ffa_sandbox_data func_data;
+	u32 fwk_version = 0;
+
+	func_data.data0 = &fwk_version;
+	func_data.data0_size = sizeof(fwk_version);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_VERSION, &func_data));
+	ut_asserteq(uc_priv->fwk_version, fwk_version);
+
+	return 0;
+}
+
+static int check_endpoint_id(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_asserteq(0, uc_priv->id);
+
+	return 0;
+}
+
+static int check_rxtxbuf(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assertnonnull(uc_priv->pair.rxbuf);
+	ut_assertnonnull(uc_priv->pair.txbuf);
+
+	return 0;
+}
+
+static int check_features(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assert(uc_priv->pair.rxtx_min_pages == RXTX_4K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_16K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_64K);
+
+	return 0;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+		ut_asserteq(1, rxbuf_mapped);
+		break;
+	case FFA_RXTX_UNMAP:
+		ut_asserteq(0, rxbuf_mapped);
+		break;
+	default:
+		ut_assert(false);
+	}
+
+	return 0;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	ut_asserteq(0, rxbuf_owned);
+
+	return 0;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg;
+	u8 cnt;
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]);
+
+	return 0;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct unit_test_state *uts)
+{
+	struct ffa_partition_desc *descs;
+	u32 count, i, j, valid_sps = 0;
+	struct udevice *dev;
+	struct ffa_sandbox_data func_data;
+	struct ffa_partitions *partitions;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get from the driver the count and information of the SPs matching the UUID */
+	ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, &descs));
+
+	/* Make sure the count is correct */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+
+	/* SPs found , verify the partitions information */
+
+	func_data.data0 = &partitions;
+	func_data.data0_size = sizeof(struct ffa_partitions *);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_PARTITION_INFO_GET, &func_data));
+
+	for (i = 0; i < count ; i++) {
+		for (j = 0;
+		     j < partitions->count;
+		     j++) {
+			if (descs[i].info.id ==
+			   partitions->descs[j].info.id) {
+				valid_sps++;
+				ut_asserteq_mem(&descs[i],
+						&partitions->descs[j],
+						sizeof(struct ffa_partition_desc));
+				/* Send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(descs[i].info.id, uts);
+			}
+		}
+	}
+
+	/* Verify expected partitions found in the emulated secure world */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, valid_sps);
+
+	return 0;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	struct ffa_sandbox_data func_data;
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	struct udevice *dev;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Test FFA_VERSION */
+	check_fwk_version(uc_priv, uts);
+
+	/* Test FFA_ID_GET */
+	check_endpoint_id(uc_priv, uts);
+
+	/* Test FFA_FEATURES */
+	check_features(uc_priv, uts);
+
+	/*  Test RX/TX buffers */
+	check_rxtxbuf(uc_priv, uts);
+
+	/* Test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	sandbox_query_ffa_emul_state(FFA_RXTX_MAP, &func_data);
+	check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc1_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data);
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc2_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data));
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg;
+	int ret;
+	u32 count;
+	u16 part_id = 0;
+	struct udevice *dev;
+	struct ffa_partition_desc *descs = NULL;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Query partitions count using  invalid arguments */
+	ret = ffa_partition_info_get(dev, NULL, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, NULL);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID  string */
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid_str, &count, &descs);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, &descs);
+	ut_asserteq(0, count);
+
+	/* Query partitions data using a valid UUID */
+	count = 0;
+	ut_assertok(ffa_partition_info_get(dev, valid_svc_uuid, &count, &descs));
+	/* Make sure partitions are detected */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+	ut_assertnonnull(descs);
+
+	/* Send data to an invalid partition */
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Send data to a valid partition */
+	part_id = uc_priv->partitions.descs[0].info.id;
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v15 08/10] arm_ffa: introduce armffa command Sandbox test
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                       ` (6 preceding siblings ...)
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-07-13 13:28                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
                                                                                                                                                       ` (4 subsequent siblings)
  12 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-13 13:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, sjg, u-boot, ilias.apalodimas, Jens Wiklander

Add Sandbox test for the armffa command

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v12:

* address nits

v10:

* replace CMD_RET_SUCCESS with 0
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT

v9: align the test with FF-A discovery through DM

v4: drop use of helper APIs

v1: introduce armffa command sandbox test

 MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4a8b3a5419..30d1b87149 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index a3cf983739..6e3d7e919e 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -24,6 +25,7 @@ obj-$(CONFIG_CMD_SEAMA) += seama.o
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_CMD_READ) += rw.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o
 endif
 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
 obj-$(CONFIG_CMD_WGET) += wget.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..9a44a397e8
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * 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 <string.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	/* armffa ping <ID> */
+	ut_assertok(run_commandf("armffa ping 0x%x", SANDBOX_SP1_ID));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return 0;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v15 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                       ` (7 preceding siblings ...)
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2023-07-13 13:28                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
                                                                                                                                                       ` (3 subsequent siblings)
  12 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-13 13:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, sjg, u-boot, ilias.apalodimas,
	Gowtham Suresh Kumar, Jens Wiklander

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

MM communication protocol supports FF-A 64-bit direct messaging.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v15:

Simon:

* replace FFA_SHARED_MM_BUFFER_* defines with configs

v14:

Ilias:

* drop truncating var_payload->size when using FF-A
* map the MM SP return codes to errnos

v13:

* remove FF-A and Optee ifdefs

v12:

* drop use of calloc when querying SPs
* address nits

v11:

* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* addressing nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* addressing nits

v9: align how FF-A is used with FF-A discovery through DM

v8:

* isolate the compilation choices between FF-A and OP-TEE
* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make mm_sp_svc_uuid static
* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
* improve use of unmap_sysmem() in ffa_mm_communicate()

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

 include/mm_communication.h        |  13 ++
 lib/efi_loader/Kconfig            |  46 +++++-
 lib/efi_loader/efi_variable_tee.c | 257 +++++++++++++++++++++++++++++-
 3 files changed, 309 insertions(+), 7 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..f17847583b 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,9 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *    Authors:
+ *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +16,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
@@ -248,4 +254,11 @@ struct smm_variable_var_check_property {
 	u16                       name[];
 };
 
+/* supported MM transports */
+enum mm_comms_select {
+	MM_COMMS_UNDEFINED,
+	MM_COMMS_FFA,
+	MM_COMMS_OPTEE
+};
+
 #endif /* _MM_COMMUNICATION_H_ */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c5835e6ef6..553e6a30a2 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,55 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	select ARM_FFA_TRANSPORT
+	select TEE
+	select OPTEE
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
+config FFA_SHARED_MM_BUF_SIZE
+	int "Memory size of the shared MM communication buffer"
+	default 0
+	depends on EFI_MM_COMM_TEE
+	help
+	  This defines the size in bytes of the memory area reserved for the shared
+	  buffer used for communication between the MM feature in U-Boot and
+	  the MM SP in secure world.
+	  The size of the memory region must be a multiple of the size of the maximum
+	  translation granule size that is specified in the ID_AA64MMFR0_EL1 System register.
+	  It is assumed that the MM SP knows the size of the shared MM communication buffer.
+
+config FFA_SHARED_MM_BUF_OFFSET
+	int "Data offset in the shared MM communication buffer"
+	default 0
+	depends on EFI_MM_COMM_TEE
+	help
+	  This defines the offset in bytes of the data read or written to in the shared
+	  buffer by the MM SP.
+
+config FFA_SHARED_MM_BUF_ADDR
+	hex "Define the address of the shared MM communication buffer"
+	default 0x0
+	depends on EFI_MM_COMM_TEE
+	help
+	  This defines the address of the shared MM communication buffer
+	  used for communication between the MM feature in U-Boot and
+	  the MM SP in secure world.
+	  It is assumed that the MM SP knows the address of the shared MM communication buffer.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..5137b871ea 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,17 +4,34 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  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 <cpu_func.h>
+#include <dm.h>
 #include <efi.h>
 #include <efi_api.h>
 #include <efi_loader.h>
 #include <efi_variable.h>
-#include <tee.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <mm_communication.h>
+#include <tee.h>
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+#define MM_NOT_SUPPORTED (-1)
+#define MM_INVALID_PARAMETER (-2)
+#define MM_DENIED (-3)
+#define MM_NO_MEMORY (-5)
 
+static const char *mm_sp_svc_uuid = MM_SP_UUID;
+static u16 mm_sp_id;
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -145,16 +162,241 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 }
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notify the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
+		return ret;
+	}
+
+	msg.data0 = CONFIG_FFA_SHARED_MM_BUF_OFFSET; /* x3 */
+
+	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
+	if (ret)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	switch (sp_event_ret) {
+	case MM_SUCCESS:
+		ret = 0;
+		break;
+	case MM_NOT_SUPPORTED:
+		ret = -EINVAL;
+		break;
+	case MM_INVALID_PARAMETER:
+		ret = -EPERM;
+		break;
+	case MM_DENIED:
+		ret = -EACCES;
+		break;
+	case MM_NO_MEMORY:
+		ret = -EBUSY;
+		break;
+	default:
+		ret = -EACCES;
+	}
+
+	return ret;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
+		return ret;
+	}
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, &descs);
+	if (ret) {
+		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
+		return ret;
+	}
+
+	/* MM SPs found , use the first one */
+
+	mm_sp_id = descs[0].info.id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	return 0;
+}
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	efi_status_t efi_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()) {
+		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > CONFIG_FFA_SHARED_MM_BUF_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = map_sysmem((phys_addr_t)CONFIG_FFA_SHARED_MM_BUF_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+
+	switch (ffa_ret) {
+	case 0: {
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		efi_ret = EFI_SUCCESS;
+		break;
+	}
+	case -EINVAL:
+		efi_ret = EFI_DEVICE_ERROR;
+		break;
+	case -EPERM:
+		efi_ret = EFI_INVALID_PARAMETER;
+		break;
+	case -EACCES:
+		efi_ret = EFI_ACCESS_DENIED;
+		break;
+	case -EBUSY:
+		efi_ret = EFI_OUT_OF_RESOURCES;
+		break;
+	default:
+		efi_ret = EFI_ACCESS_DENIED;
+	}
+
+	unmap_sysmem(virt_shared_buf);
+	return efi_ret;
+}
+
+/**
+ * get_mm_comms() - detect the available MM transport
+ *
+ * Make sure the FF-A bus is probed successfully
+ * which means FF-A communication with secure world works and ready
+ * for use.
+ *
+ * If FF-A bus is not ready, use OPTEE comms.
+ *
+ * Return:
+ *
+ * MM_COMMS_FFA or MM_COMMS_OPTEE
+ */
+static enum mm_comms_select get_mm_comms(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, trying Optee comms\n");
+		return MM_COMMS_OPTEE;
+	}
+
+	return MM_COMMS_FFA;
+}
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 {
 	efi_status_t ret;
+	enum mm_comms_select mm_comms;
 	struct efi_mm_communicate_header *mm_hdr;
 	struct smm_variable_communicate_header *var_hdr;
 
@@ -162,7 +404,12 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+	mm_comms = get_mm_comms();
+	if (mm_comms == MM_COMMS_FFA)
+		ret = ffa_mm_communicate(comm_buf, dsize);
+	else
+		ret = optee_mm_communicate(comm_buf, dsize);
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -697,7 +944,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v15 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                       ` (8 preceding siblings ...)
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-07-13 13:28                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-24 18:29                                                                                                                                     ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                       ` (2 subsequent siblings)
  12 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-13 13:28 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, sjg, u-boot, ilias.apalodimas, Jens Wiklander

turn on EFI MM communication

On corstone1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

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>

---

Changelog:
===============

v15:

Simon:

* use CONFIG_FFA_SHARED_MM_BUF_* configs in place of FFA_SHARED_MM_BUFFER_*

v13:

* remove FF-A config in the defconfig
   (because it's enabled automatically by CONFIG_EFI_MM_COMM_TEE)

v9:

* update copyright string

v8:

* drop OP-TEE configs from Corstone-1000 defconfig

v7:

* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
  FFA_SHARED_MM_BUFFER_OFFSET
* update FFA_SHARED_MM_BUFFER_ADDR value

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

 configs/corstone1000_defconfig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index a8a79fd105..5689712545 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -65,3 +65,7 @@ CONFIG_EFI_CAPSULE_ON_DISK=y
 CONFIG_EFI_IGNORE_OSINDICATIONS=y
 CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
+CONFIG_FFA_SHARED_MM_BUF_SIZE=4096
+CONFIG_FFA_SHARED_MM_BUF_OFFSET=0
+CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v15 00/10] introduce Arm FF-A support
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                       ` (9 preceding siblings ...)
  2023-07-13 13:28                                                                                                                                     ` [PATCH v15 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
@ 2023-07-24 18:29                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-24 23:01                                                                                                                                     ` Tom Rini
  2023-07-24 23:50                                                                                                                                     ` Tom Rini
  12 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-24 18:29 UTC (permalink / raw)
  To: trini; +Cc: sjg, u-boot, nd

Hi Tom, Simon,

On Thu, Jul 13, 2023 at 02:28:37PM +0100, Abdellatif El Khlifi wrote:
> Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> 
> FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> communicate with each other. A partition could be a VM in the Normal or Secure world, an
> application in S-EL0, or a Trusted OS in S-EL1.
> 
> FF-A is a discoverable bus and similar to architecture features.
> FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> by the PSCI driver.
> 
>    => dm tree
> 
>     Class     Index  Probed  Driver                Name
>    -----------------------------------------------------------
>    ...
>     firmware      0  [ + ]   psci                      |-- psci
>     ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
>    ...
> 
> Clients are able to probe then use the FF-A bus by calling the DM class
> searching APIs (e.g: uclass_first_device).
> 
> This implementation of the specification provides support for Aarch64.
> 
> The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> 
>     - Discover the presence of secure partitions (SPs) of interest
>     - Access an SP's service through communication protocols
>       (e.g: EFI MM communication protocol)
> 
> The FF-A support provides the following features:
> 
>     - Being generic by design and can be used by any Arm 64-bit platform
>     - FF-A support can be compiled and used without EFI
>     - Support for SMCCCv1.2 x0-x17 registers
>     - Support for SMC32 calling convention
>     - Support for 32-bit and 64-bit FF-A direct messaging
>     - Support for FF-A MM communication (compatible with EFI boot time)
>     - Enabling FF-A and MM communication in Corstone1000 platform as a use case
>     - 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.
>     - Sandbox FF-A test cases.
>     - A new command called armffa is provided as an example of how to access the
>       FF-A bus
> 
> For more details about the FF-A support please refer to [B] and refer to [C] for
> how to use the armffa command.
> 
> Please find at [D] an example of the expected boot logs when enabling
> FF-A support for a platform. In this example the platform is
> Corstone1000. But it can be any Arm 64-bit platform.
> 
> Changelog of changes:
> ===========================
> 
> v15:
> 
> Simon:
> 
> * drop commit "log: select physical address formatting in a generic way",
>    this will be sent as a follow-up commit independently from this patchset
> * armffa.c : integrate PHYS_ADDR_LN
> * replace FFA_SHARED_MM_BUFFER_* defines with configs
> 

A gentle reminder about this patchset. All remaining comments have been addressed in v15.

Cheers
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v15 00/10] introduce Arm FF-A support
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                       ` (10 preceding siblings ...)
  2023-07-24 18:29                                                                                                                                     ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-07-24 23:01                                                                                                                                     ` Tom Rini
  2023-07-24 23:50                                                                                                                                     ` Tom Rini
  12 siblings, 0 replies; 478+ messages in thread
From: Tom Rini @ 2023-07-24 23:01 UTC (permalink / raw)
  To: u-boot, Abdellatif El Khlifi
  Cc: nd, sjg, ilias.apalodimas, Rob Herring, Jens Wiklander,
	Achin Gupta, Drew Reed, Xueliang Zhong

On Thu, 13 Jul 2023 14:28:37 +0100, Abdellatif El Khlifi wrote:

> Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> 
> FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> communicate with each other. A partition could be a VM in the Normal or Secure world, an
> application in S-EL0, or a Trusted OS in S-EL1.
> 
> FF-A is a discoverable bus and similar to architecture features.
> FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> by the PSCI driver.
> 
> [...]

Applied to u-boot/master, thanks!

-- 
Tom


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v15 00/10] introduce Arm FF-A support
  2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                       ` (11 preceding siblings ...)
  2023-07-24 23:01                                                                                                                                     ` Tom Rini
@ 2023-07-24 23:50                                                                                                                                     ` Tom Rini
  2023-07-25  9:26                                                                                                                                       ` Abdellatif El Khlifi
  12 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-07-24 23:50 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: nd, sjg, u-boot, ilias.apalodimas, Rob Herring, Jens Wiklander,
	Achin Gupta, Drew Reed, Xueliang Zhong

[-- Attachment #1: Type: text/plain, Size: 3114 bytes --]

On Thu, Jul 13, 2023 at 02:28:37PM +0100, Abdellatif El Khlifi wrote:
> Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> 
> FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> communicate with each other. A partition could be a VM in the Normal or Secure world, an
> application in S-EL0, or a Trusted OS in S-EL1.
> 
> FF-A is a discoverable bus and similar to architecture features.
> FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> by the PSCI driver.
> 
>    => dm tree
> 
>     Class     Index  Probed  Driver                Name
>    -----------------------------------------------------------
>    ...
>     firmware      0  [ + ]   psci                      |-- psci
>     ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
>    ...
> 
> Clients are able to probe then use the FF-A bus by calling the DM class
> searching APIs (e.g: uclass_first_device).
> 
> This implementation of the specification provides support for Aarch64.
> 
> The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> 
>     - Discover the presence of secure partitions (SPs) of interest
>     - Access an SP's service through communication protocols
>       (e.g: EFI MM communication protocol)
> 
> The FF-A support provides the following features:
> 
>     - Being generic by design and can be used by any Arm 64-bit platform
>     - FF-A support can be compiled and used without EFI
>     - Support for SMCCCv1.2 x0-x17 registers
>     - Support for SMC32 calling convention
>     - Support for 32-bit and 64-bit FF-A direct messaging
>     - Support for FF-A MM communication (compatible with EFI boot time)
>     - Enabling FF-A and MM communication in Corstone1000 platform as a use case
>     - 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.
>     - Sandbox FF-A test cases.
>     - A new command called armffa is provided as an example of how to access the
>       FF-A bus
> 
> For more details about the FF-A support please refer to [B] and refer to [C] for
> how to use the armffa command.
> 
> Please find at [D] an example of the expected boot logs when enabling
> FF-A support for a platform. In this example the platform is
> Corstone1000. But it can be any Arm 64-bit platform.
> 
> Changelog of changes:
> ===========================
> 
> v15:

So, this does not pass CI:
https://source.denx.de/u-boot/u-boot/-/jobs/662303
https://source.denx.de/u-boot/u-boot/-/jobs/662304#L2234

And it's on me for merging this before letting the CI run I kicked
complete, sorry.  But I'm reverting this now.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v15 00/10] introduce Arm FF-A support
  2023-07-24 23:50                                                                                                                                     ` Tom Rini
@ 2023-07-25  9:26                                                                                                                                       ` Abdellatif El Khlifi
  2023-07-25 13:47                                                                                                                                         ` Tom Rini
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-25  9:26 UTC (permalink / raw)
  To: Tom Rini; +Cc: nd, u-boot

Hi Tom,

On Mon, Jul 24, 2023 at 07:50:07PM -0400, Tom Rini wrote:
> On Thu, Jul 13, 2023 at 02:28:37PM +0100, Abdellatif El Khlifi wrote:
> > Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> > 
> > FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> > communicate with each other. A partition could be a VM in the Normal or Secure world, an
> > application in S-EL0, or a Trusted OS in S-EL1.
> > 
> > FF-A is a discoverable bus and similar to architecture features.
> > FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> > by the PSCI driver.
> > 
> > ...
> > 
> > Changelog of changes:
> > ===========================
> > 
> > v15:
> 
> So, this does not pass CI:
> https://source.denx.de/u-boot/u-boot/-/jobs/662303
> https://source.denx.de/u-boot/u-boot/-/jobs/662304#L2234
> 
> And it's on me for merging this before letting the CI run I kicked
> complete, sorry.  But I'm reverting this now.
> 

The v15 patchset has been built successfully on next using this SHA: [1].

The tested platforms are the following: [2].

Is there any action from my side please ?

[1]: 56c7fac8ad89955d3e5d08864bbd1343a058bf4b
[2]: tested platforms

sandbox64
sandbox
corstone1000-fvp
corstone1000-mps3
qemu_arm64

Cheers,
Abdellatif


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v15 00/10] introduce Arm FF-A support
  2023-07-25  9:26                                                                                                                                       ` Abdellatif El Khlifi
@ 2023-07-25 13:47                                                                                                                                         ` Tom Rini
  2023-07-25 18:34                                                                                                                                           ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-07-25 13:47 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: nd, u-boot

[-- Attachment #1: Type: text/plain, Size: 1907 bytes --]

On Tue, Jul 25, 2023 at 10:26:16AM +0100, Abdellatif El Khlifi wrote:
> Hi Tom,
> 
> On Mon, Jul 24, 2023 at 07:50:07PM -0400, Tom Rini wrote:
> > On Thu, Jul 13, 2023 at 02:28:37PM +0100, Abdellatif El Khlifi wrote:
> > > Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> > > 
> > > FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> > > communicate with each other. A partition could be a VM in the Normal or Secure world, an
> > > application in S-EL0, or a Trusted OS in S-EL1.
> > > 
> > > FF-A is a discoverable bus and similar to architecture features.
> > > FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> > > by the PSCI driver.
> > > 
> > > ...
> > > 
> > > Changelog of changes:
> > > ===========================
> > > 
> > > v15:
> > 
> > So, this does not pass CI:
> > https://source.denx.de/u-boot/u-boot/-/jobs/662303
> > https://source.denx.de/u-boot/u-boot/-/jobs/662304#L2234
> > 
> > And it's on me for merging this before letting the CI run I kicked
> > complete, sorry.  But I'm reverting this now.
> > 
> 
> The v15 patchset has been built successfully on next using this SHA: [1].
> 
> The tested platforms are the following: [2].
> 
> Is there any action from my side please ?
> 
> [1]: 56c7fac8ad89955d3e5d08864bbd1343a058bf4b
> [2]: tested platforms
> 
> sandbox64
> sandbox
> corstone1000-fvp
> corstone1000-mps3
> qemu_arm64

Yes, you need to go and fix all of the problems that CI is showing:
- On 64bit, espresso7420 is building cmd/armffa.c and pointing out an
  unused variable.
- Maybe related to why that platform is building the code, a ton of
  32bit platforms are building the code and showing warnings.  And also
  that your Kconfig logic is wrong.
- Finally, the MAINTAINERS file needs to be alphabetical.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v15 00/10] introduce Arm FF-A support
  2023-07-25 13:47                                                                                                                                         ` Tom Rini
@ 2023-07-25 18:34                                                                                                                                           ` Abdellatif El Khlifi
  2023-07-25 18:52                                                                                                                                             ` Tom Rini
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-25 18:34 UTC (permalink / raw)
  To: Tom Rini; +Cc: nd, u-boot

Hi Tom,

On Tue, Jul 25, 2023 at 09:47:24AM -0400, Tom Rini wrote:
> On Tue, Jul 25, 2023 at 10:26:16AM +0100, Abdellatif El Khlifi wrote:
> > Hi Tom,
> > 
> > On Mon, Jul 24, 2023 at 07:50:07PM -0400, Tom Rini wrote:
> > > On Thu, Jul 13, 2023 at 02:28:37PM +0100, Abdellatif El Khlifi wrote:
> > > > Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> > > > 
> > > > FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> > > > communicate with each other. A partition could be a VM in the Normal or Secure world, an
> > > > application in S-EL0, or a Trusted OS in S-EL1.
> > > > 
> > > > FF-A is a discoverable bus and similar to architecture features.
> > > > FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> > > > by the PSCI driver.
> > > > 
> > > > ...
> > > > 
> > > > Changelog of changes:
> > > > ===========================
> > > > 
> > > > v15:
> > > 
> > > So, this does not pass CI:
> > > https://source.denx.de/u-boot/u-boot/-/jobs/662303
> > > https://source.denx.de/u-boot/u-boot/-/jobs/662304#L2234
> > > 
> > > And it's on me for merging this before letting the CI run I kicked
> > > complete, sorry.  But I'm reverting this now.
> > > 
> > 
> > The v15 patchset has been built successfully on next using this SHA: [1].
> > 
> > The tested platforms are the following: [2].
> > 
> > Is there any action from my side please ?
> > 
> > [1]: 56c7fac8ad89955d3e5d08864bbd1343a058bf4b
> > [2]: tested platforms
> > 
> > sandbox64
> > sandbox
> > corstone1000-fvp
> > corstone1000-mps3
> > qemu_arm64
> 
> Yes, you need to go and fix all of the problems that CI is showing:
> - On 64bit, espresso7420 is building cmd/armffa.c and pointing out an
>   unused variable.
> - Maybe related to why that platform is building the code, a ton of
>   32bit platforms are building the code and showing warnings.  And also
>   that your Kconfig logic is wrong.
> - Finally, the MAINTAINERS file needs to be alphabetical.
> 

Thanks for the details. I fixed all the issues and will send them shortly in v16 (a minor change).

espresso7420 builds fine and Arm 32-bit boards no longer automatically pick up FF-A.

For the alphabetical order in MAINTAINERS, please help me undertand where the issue is.
The FF-A part is already in alphabetical order:

ARM CORTINA ACCESS CAxxxx
...

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:	test/cmd/armffa.c
F:	test/dm/ffa.c

ARM FREESCALE IMX
...

Cheers,
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v15 00/10] introduce Arm FF-A support
  2023-07-25 18:34                                                                                                                                           ` Abdellatif El Khlifi
@ 2023-07-25 18:52                                                                                                                                             ` Tom Rini
  2023-07-26  9:44                                                                                                                                               ` [PATCH v16 " Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-07-25 18:52 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: nd, u-boot

[-- Attachment #1: Type: text/plain, Size: 2701 bytes --]

On Tue, Jul 25, 2023 at 07:34:39PM +0100, Abdellatif El Khlifi wrote:
> Hi Tom,
> 
> On Tue, Jul 25, 2023 at 09:47:24AM -0400, Tom Rini wrote:
> > On Tue, Jul 25, 2023 at 10:26:16AM +0100, Abdellatif El Khlifi wrote:
> > > Hi Tom,
> > > 
> > > On Mon, Jul 24, 2023 at 07:50:07PM -0400, Tom Rini wrote:
> > > > On Thu, Jul 13, 2023 at 02:28:37PM +0100, Abdellatif El Khlifi wrote:
> > > > > Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> > > > > 
> > > > > FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> > > > > communicate with each other. A partition could be a VM in the Normal or Secure world, an
> > > > > application in S-EL0, or a Trusted OS in S-EL1.
> > > > > 
> > > > > FF-A is a discoverable bus and similar to architecture features.
> > > > > FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> > > > > by the PSCI driver.
> > > > > 
> > > > > ...
> > > > > 
> > > > > Changelog of changes:
> > > > > ===========================
> > > > > 
> > > > > v15:
> > > > 
> > > > So, this does not pass CI:
> > > > https://source.denx.de/u-boot/u-boot/-/jobs/662303
> > > > https://source.denx.de/u-boot/u-boot/-/jobs/662304#L2234
> > > > 
> > > > And it's on me for merging this before letting the CI run I kicked
> > > > complete, sorry.  But I'm reverting this now.
> > > > 
> > > 
> > > The v15 patchset has been built successfully on next using this SHA: [1].
> > > 
> > > The tested platforms are the following: [2].
> > > 
> > > Is there any action from my side please ?
> > > 
> > > [1]: 56c7fac8ad89955d3e5d08864bbd1343a058bf4b
> > > [2]: tested platforms
> > > 
> > > sandbox64
> > > sandbox
> > > corstone1000-fvp
> > > corstone1000-mps3
> > > qemu_arm64
> > 
> > Yes, you need to go and fix all of the problems that CI is showing:
> > - On 64bit, espresso7420 is building cmd/armffa.c and pointing out an
> >   unused variable.
> > - Maybe related to why that platform is building the code, a ton of
> >   32bit platforms are building the code and showing warnings.  And also
> >   that your Kconfig logic is wrong.
> > - Finally, the MAINTAINERS file needs to be alphabetical.
> > 
> 
> Thanks for the details. I fixed all the issues and will send them shortly in v16 (a minor change).
> 
> espresso7420 builds fine and Arm 32-bit boards no longer automatically pick up FF-A.

Thanks.

> 
> For the alphabetical order in MAINTAINERS, please help me undertand where the issue is.
> The FF-A part is already in alphabetical order:
> 
> ARM CORTINA ACCESS CAxxxx

The UUID test portion was not, however.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v16 00/10] introduce Arm FF-A support
  2023-07-25 18:52                                                                                                                                             ` Tom Rini
@ 2023-07-26  9:44                                                                                                                                               ` Abdellatif El Khlifi
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                                                                                                                                   ` (9 more replies)
  0 siblings, 10 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-26  9:44 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, u-boot, Simon Glass, Rob Herring,
	Ilias Apalodimas, Jens Wiklander, Achin Gupta, Drew Reed,
	Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].

FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
communicate with each other. A partition could be a VM in the Normal or Secure world, an
application in S-EL0, or a Trusted OS in S-EL1.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

   => dm tree

    Class     Index  Probed  Driver                Name
   -----------------------------------------------------------
   ...
    firmware      0  [ + ]   psci                      |-- psci
    ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
   ...

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

This implementation of the specification provides support for Aarch64.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

    - Discover the presence of secure partitions (SPs) of interest
    - Access an SP's service through communication protocols
      (e.g: EFI MM communication protocol)

The FF-A support provides the following features:

    - Being generic by design and can be used by any Arm 64-bit platform
    - FF-A support can be compiled and used without EFI
    - Support for SMCCCv1.2 x0-x17 registers
    - Support for SMC32 calling convention
    - Support for 32-bit and 64-bit FF-A direct messaging
    - Support for FF-A MM communication (compatible with EFI boot time)
    - Enabling FF-A and MM communication in Corstone1000 platform as a use case
    - 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.
    - Sandbox FF-A test cases.
    - A new command called armffa is provided as an example of how to access the
      FF-A bus

For more details about the FF-A support please refer to [B] and refer to [C] for
how to use the armffa command.

Please find at [D] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of changes:
===========================

v16:

Tom:

* lib/efi_loader/Kconfig:
   rather than automatically selecting OPTEE and ARM_FFA_TRANSPORT configs by
   EFI_MM_COMM_TEE, set them as dependencies (Otherwise FF-A will be automatically
   enabled for boards that don't need it).

* configs/corstone1000_defconfig:
   enable MM communication by setting the configs: ARM_FFA_TRANSPORT, OPTEE, TEE

v15: [15]

Simon:

* drop commit "log: select physical address formatting in a generic way",
   this will be sent as a follow-up commit independently from this patchset
* armffa.c : integrate PHYS_ADDR_LN
* replace FFA_SHARED_MM_BUFFER_* defines with configs

v14: [14]

Simon:

    * add to log.h a generic physical address formatting

Ilias:

    * armffa command: in do_ffa_ping() reject the SP ID if it's 0
    * MM comms: drop truncating var_payload->size when using FF-A
    * MM comms: map the MM SP return codes to errnos
    * address nits

v13: [13]

Ilias:
    * remove FF-A and Optee ifdefs in efi_variable_tee.c
    * doc minor change: specify in the readme that the user
       should call ffa_rxtx_unmap() driver operation to unmap
       the RX/TX buffers on demand.

v12: [12]

* remove the global variable (dscvry_info), use uc_priv instead
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* remove reparenting by making the sandbox emulator parent of the FF-A device in the DT
* improve argument checks for the armffa command
* address nits

v11: [11]

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* use U_BOOT_CMD_WITH_SUBCMDS for armffa command
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device
* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* use ut_asserteq_mem() in uuid_str_to_le_bin test case
* address nits

v10: [10]

* provide the FF-A driver operations through the Uclass (arm-ffa-uclass.c)
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c renamed from core.c)
* split the FF-A sandbox support into an emulator (ffa-emul-uclass.c) and a driver (sandbox_ffa.c)
* use the FF-A driver Uclass operations by clients (armffa command, tests, MM comms)
* use uclass_first_device to search and probe the FF-A device (whether it is on Arm or on sandbox)
* address nits

v9: [9]

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
* align FF-A sandbox driver with FF-A discovery through DM
* use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
* add documentation for the armffa command: doc/usage/cmd/armffa.rst
* introduce testcase for uuid_str_to_le_bin

v8: [8]

* pass the FF-A bus device to the bus operations
* isolate the compilation choices between FF-A and OP-TEE
* drop OP-TEE configs from Corstone-1000 defconfig
* make ffa_get_partitions_info() second argument to be an SP count in both
  modes

v7: [7]

* add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v6: [6]

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

List of previous patches:

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
[7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
[8]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
[9]: https://lore.kernel.org/all/20230310141016.137986-1-abdellatif.elkhlifi@arm.com/
[10]: https://lore.kernel.org/all/20230328161157.219375-1-abdellatif.elkhlifi@arm.com/
[11]: https://lore.kernel.org/all/20230412094245.44674-1-abdellatif.elkhlifi@arm.com/
[12]: https://lore.kernel.org/all/20230512121044.111574-1-abdellatif.elkhlifi@arm.com/
[13]: https://lore.kernel.org/all/20230616152817.319869-1-abdellatif.elkhlifi@arm.com/
[14]: https://lore.kernel.org/all/20230707144410.228472-1-abdellatif.elkhlifi@arm.com/
[15]: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/

More details:

[A]: https://developer.arm.com/documentation/den0077/latest/
[B]: doc/arch/arm64.ffa.rst
[C]: doc/usage/cmd/armffa.rst
[D]: example of boot logs when enabling FF-A

```
   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64

   DRAM:  2 GiB
   Arm FF-A framework discovery
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   ...
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   EFI: MM partition ID 0x8003
   ...
   EFI stub: Booting Linux Kernel...
   ...
   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
   Machine model: ARM Corstone1000 FPGA MPS3 board
```

Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (10):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce uuid_str_to_le_bin function
  lib: uuid: introduce testcase for uuid_str_to_le_bin
  arm_ffa: introduce Arm FF-A support
  arm_ffa: introduce armffa command
  arm_ffa: introduce sandbox FF-A support
  arm_ffa: introduce sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   18 +
 arch/arm/cpu/armv8/smccc-call.S               |   57 +-
 arch/arm/lib/asm-offsets.c                    |   16 +
 arch/sandbox/dts/sandbox.dtsi                 |    9 +
 arch/sandbox/dts/test.dts                     |    8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |   72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        |  121 ++
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    1 +
 cmd/armffa.c                                  |  202 ++++
 configs/corstone1000_defconfig                |    7 +
 configs/sandbox64_defconfig                   |    1 +
 configs/sandbox_defconfig                     |    1 +
 doc/arch/arm64.ffa.rst                        |  261 ++++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox/sandbox.rst                  |    1 +
 doc/usage/cmd/armffa.rst                      |   94 ++
 doc/usage/index.rst                           |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   42 +
 drivers/firmware/arm-ffa/Makefile             |   16 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 drivers/firmware/arm-ffa/ffa-emul-uclass.c    |  720 +++++++++++
 drivers/firmware/arm-ffa/sandbox_ffa.c        |  110 ++
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/dm/uclass-id.h                        |    7 +
 include/linux/arm-smccc.h                     |   45 +
 include/mm_communication.h                    |   13 +
 include/uuid.h                                |   15 +
 lib/efi_loader/Kconfig                        |   44 +-
 lib/efi_loader/efi_variable_tee.c             |  257 +++-
 lib/uuid.c                                    |   48 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   33 +
 test/dm/Makefile                              |    3 +-
 test/dm/ffa.c                                 |  261 ++++
 test/lib/Makefile                             |    1 +
 test/lib/uuid.c                               |   41 +
 41 files changed, 4160 insertions(+), 9 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 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 doc/usage/cmd/armffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/lib/uuid.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v16 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-07-26  9:44                                                                                                                                               ` [PATCH v16 " Abdellatif El Khlifi
@ 2023-07-26  9:44                                                                                                                                                 ` Abdellatif El Khlifi
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
                                                                                                                                                                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-26  9:44 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, u-boot, Ilias Apalodimas,
	Jens Wiklander, Simon Glass

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>

---

Changelog:
===============

v9:

* update the copyright string

v7:

* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
 arch/arm/lib/asm-offsets.c      | 16 +++++++++
 include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..93f66d3366 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,7 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
- */
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+*/
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
 #include <generated/asm-offsets.h>
@@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 6de0ce9152..181a8ac4c2 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,11 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * 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>
@@ -90,6 +95,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#ifdef CONFIG_ARM64
+	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..f44e9e8f93 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +74,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v16 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2023-07-26  9:44                                                                                                                                               ` [PATCH v16 " Abdellatif El Khlifi
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-07-26  9:44                                                                                                                                                 ` Abdellatif El Khlifi
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
                                                                                                                                                                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-26  9:44 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, u-boot, Simon Glass, Ilias Apalodimas,
	Jens Wiklander

convert UUID string to little endian binary data

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v9:

* add a full function prototype description in uuid.h

v8:

* use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

include/uuid.h | 15 +++++++++++++++
 lib/uuid.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..89b93e642b 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,10 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +48,15 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ * Return:
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 96e1af3c8b..45f325d964 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * 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>
@@ -354,6 +358,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16;
+	u32 tmp32;
+	u64 tmp64;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+	memcpy(uuid_bin, &tmp32, 4);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16));
+	memcpy(uuid_bin + 10, &tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v16 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-07-26  9:44                                                                                                                                               ` [PATCH v16 " Abdellatif El Khlifi
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2023-07-26  9:44                                                                                                                                                 ` Abdellatif El Khlifi
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-26  9:44 UTC (permalink / raw)
  To: trini; +Cc: abdellatif.elkhlifi, nd, u-boot, Simon Glass

provide a test case

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>

---

Changelog:
===============

v16:

* MAINTAINERS: place the UUID part in an alphabetical order

v11:

* use ut_asserteq_mem()

MAINTAINERS       |  5 +++++
 test/lib/Makefile |  1 +
 test/lib/uuid.c   | 41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)
 create mode 100644 test/lib/uuid.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d724b64673..4324965d26 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1555,6 +1555,11 @@ T:	git https://source.denx.de/u-boot/custodians/u-boot-usb.git topic-xhci
 F:	drivers/usb/host/xhci*
 F:	include/usb/xhci.h
 
+UUID testing
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	test/lib/uuid.c
+
 VIDEO
 M:	Anatolij Gustschin <agust@denx.de>
 S:	Maintained
diff --git a/test/lib/Makefile b/test/lib/Makefile
index e0bd9e04e8..e75a263e6a 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_AES) += test_aes.o
 obj-$(CONFIG_GETOPT) += getopt.o
 obj-$(CONFIG_CRC8) += test_crc8.o
 obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o
+obj-$(CONFIG_LIB_UUID) += uuid.o
 else
 obj-$(CONFIG_SANDBOX) += kconfig_spl.o
 endif
diff --git a/test/lib/uuid.c b/test/lib/uuid.c
new file mode 100644
index 0000000000..e24331a136
--- /dev/null
+++ b/test/lib/uuid.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <uuid.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* test UUID */
+#define TEST_SVC_UUID	"ed32d533-4209-99e6-2d72-cdd998a79cc0"
+
+#define UUID_SIZE 16
+
+/* The UUID binary data (little-endian format) */
+static const u8 ref_uuid_bin[UUID_SIZE] = {
+	0x33, 0xd5, 0x32, 0xed,
+	0x09, 0x42, 0xe6, 0x99,
+	0x72, 0x2d, 0xc0, 0x9c,
+	0xa7, 0x98, 0xd9, 0xcd
+};
+
+static int lib_test_uuid_to_le(struct unit_test_state *uts)
+{
+	const char *uuid_str = TEST_SVC_UUID;
+	u8 ret_uuid_bin[UUID_SIZE] = {0};
+
+	ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin));
+	ut_asserteq_mem(ref_uuid_bin, ret_uuid_bin, UUID_SIZE);
+
+	return 0;
+}
+
+LIB_TEST(lib_test_uuid_to_le, 0);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v16 04/10] arm_ffa: introduce Arm FF-A support
  2023-07-26  9:44                                                                                                                                               ` [PATCH v16 " Abdellatif El Khlifi
                                                                                                                                                                   ` (2 preceding siblings ...)
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-07-26  9:44                                                                                                                                                 ` Abdellatif El Khlifi
  2023-07-27  9:56                                                                                                                                                   ` Ilias Apalodimas
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                                                                                                                                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-26  9:44 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, u-boot, Simon Glass, Ilias Apalodimas,
	Jens Wiklander, Heinrich Schuchardt

Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- ffa_partition_info_get
- ffa_sync_send_receive
- ffa_rxtx_unmap

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 please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v13:

* doc minor change: specify in the readme that the user
   should call ffa_rxtx_unmap() driver operation to unmap
   the RX/TX buffers on demand.

v12:

* remove dscvry_info
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* address nits

v11:

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* pass dev as an argument of arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* add emul field in struct ffa_discovery_info
* address nits

v10:

* provide the driver operations through the Uclass
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c)
* rename core.c to arm-ffa.c
* address nits

v9:

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding

v8:

* make ffa_get_partitions_info() second argument to be an SP count in both
  modes
* update ffa_bus_prvdata_get() to return a pointer rather than a pointer
  address
* remove packing from ffa_partition_info and ffa_send_direct_data structures
* pass the FF-A bus device to the bus operations

v7:

* add support for 32-bit direct messaging
* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* improve the declaration of error handling mapping
* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the U-Boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the U-Boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

MAINTAINERS                                   |    8 +
 doc/arch/arm64.ffa.rst                        |  238 ++++
 doc/arch/index.rst                            |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   36 +
 drivers/firmware/arm-ffa/Makefile             |    8 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |   14 +
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/dm/uclass-id.h                        |    6 +
 13 files changed, 1941 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 4324965d26..4fd5768de0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,6 +266,14 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+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>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..4f817f053c
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,238 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Support
+================
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
+communicate with each other. A partition could be a VM in the Normal or Secure world, an
+application in S-EL0, or a Trusted OS in S-EL1.
+
+The U-Boot FF-A support (the bus) implements the interfaces to communicate
+with partitions in the Secure world aka Secure partitions (SPs).
+
+The FF-A support specifically focuses on communicating with SPs that
+isolate portions of EFI runtime services that must run in a protected
+environment which is inaccessible by the Host OS or Hypervisor.
+Examples of such services are set/get variables.
+
+The FF-A support uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+At this stage of development only EFI boot-time services are supported.
+Runtime support will be added in future developments.
+
+The U-Boot FF-A support provides the following parts:
+
+- A Uclass driver providing generic FF-A methods.
+- An Arm FF-A device driver providing Arm-specific methods and reusing the Uclass methods.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the U-Boot FF-A support relies on
+`FF-A v1.0 specification`_ and uses SMC32 calling convention which
+means using the first 32-bit data of the Xn registers.
+
+At this stage we only need the FF-A v1.0 features.
+
+The FF-A support has been tested with OP-TEE which supports SMC32 calling
+convention.
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A support uses 64-bit registers as per `SMC Calling Convention v1.2 specification`_.
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+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.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers.
+Then, an SMC instruction is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-Boot Arm FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs.
+
+FF-A bus discovery on Arm 64-bit platforms
+---------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
+an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
+This discovery mechanism is performed by the PSCI driver.
+
+The PSCI driver comes with a PSCI device tree node which is the root node for all
+architecture features including FF-A bus.
+
+::
+
+   => dm tree
+
+    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.
+
+In case of FF-A, the callback is arm_ffa_is_supported() which tries to discover the
+FF-A framework by querying the FF-A framework version from secure world using
+FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
+mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver
+with the device using device_bind_driver().
+
+At this stage the FF-A bus is registered with the DM and can be interacted with using
+the DM APIs.
+
+Clients are able to probe then use the FF-A bus by calling uclass_first_device().
+Please refer to the armffa command implementation as an example of how to probe
+and interact with the FF-A bus.
+
+When calling uclass_first_device(), the FF-A driver is probed and ends up calling
+ffa_do_probe() provided by the Uclass which does the following:
+
+    - saving the FF-A framework version in uc_priv
+    - querying from secure world the u-boot endpoint ID
+    - querying from secure world the supported features of FFA_RXTX_MAP
+    - mapping the RX/TX buffers
+    - querying from secure world all the partitions information
+
+When one of the above actions fails, probing fails and the driver stays not active
+and can be probed again if needed.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must query the SPs they are looking for
+during EFI boot-time mode using the service UUID.
+
+The RX/TX buffers are only available at EFI boot-time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped before EFI runtime mode starts.
+The driver provides a bus operation for that called ffa_rxtx_unmap().
+
+The user should call ffa_rxtx_unmap() to unmap the RX/TX buffers when required
+(e.g: at efi_exit_boot_services()).
+
+The Linux kernel allocates its own RX/TX buffers. To be able to register these kernel buffers
+with secure world, the U-Boot's RX/TX buffers should be unmapped before EFI runtime starts.
+
+When invoking FF-A direct messaging, clients should specify which ABI protocol
+they want to use (32-bit vs 64-bit). Selecting the protocol means using
+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
+The calling convention between U-Boot and the secure world stays the same: SMC32.
+
+Requirements for user drivers
+-------------------------------------
+
+Users who want to implement their custom FF-A device driver while reusing the FF-A Uclass can do so
+by implementing their own invoke_ffa_fn() in the user driver.
+
+The bus driver layer
+------------------------------
+
+FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c
+
+The following features are provided:
+
+- Support for the 32-bit version of the following ABIs:
+
+    - FFA_VERSION
+    - FFA_ID_GET
+    - FFA_FEATURES
+    - FFA_PARTITION_INFO_GET
+    - FFA_RXTX_UNMAP
+    - FFA_RX_RELEASE
+    - FFA_RUN
+    - FFA_ERROR
+    - FFA_SUCCESS
+    - FFA_INTERRUPT
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Support for the 64-bit version of the following ABIs:
+
+    - FFA_RXTX_MAP
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, FF-A support takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- FF-A support provides driver operations to be used by upper layers:
+
+    - ffa_partition_info_get
+    - ffa_sync_send_receive
+    - ffa_rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+Example of boot logs with FF-A enabled
+--------------------------------------
+
+For example, when using FF-A with Corstone-1000 the logs are as follows:
+
+::
+
+   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64
+
+   DRAM:  2 GiB
+   Arm FF-A framework discovery
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   ...
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   EFI: MM partition ID 0x8003
+   ...
+   EFI stub: Booting Linux Kernel...
+   ...
+   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
+   Machine model: ARM Corstone1000 FPGA MPS3 board
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+
+.. _`FF-A v1.0 specification`: https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e
+.. _`SMC Calling Convention v1.2 specification`: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index b8da4b8c8e..2f916f4026 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Makefile b/drivers/Makefile
index 78dcf62f76..5044f45253 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -115,6 +115,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index eae1c8ddc9..8789b1ea14 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
 	  the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
 	  services if any and reported as supported by the SMCCC firmware.
 
+source "drivers/firmware/arm-ffa/Kconfig"
 source "drivers/firmware/scmi/Kconfig"
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..9200c8028b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select ARM_SMCCC_FEATURES
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
+	  FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
+	  by the PSCI driver.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  The FF-A support on U-Boot  takes care of all the interactions between Normal
+	  world and Secure World.
+
+	  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
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..11b1766285
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,8 @@
+# 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>
+
+obj-y += arm-ffa-uclass.o arm-ffa.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..ffa9d81fa7
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,1065 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	[NOT_SUPPORTED] = -EOPNOTSUPP,
+	[INVALID_PARAMETERS] = -EINVAL,
+	[NO_MEMORY] = -ENOMEM,
+	[BUSY] = -EBUSY,
+	[INTERRUPTED] = -EINTR,
+	[DENIED] = -EACCES,
+	[RETRY] = -EAGAIN,
+	[ABORTED] = -ECANCELED,
+};
+
+static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			[NO_MEMORY] =
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			[BUSY] =
+			"BUSY: RX buffer of the caller is not free",
+			[DENIED] =
+			"DENIED: Callee is not in a state to handle this request",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			[DENIED] =
+			"DENIED: Caller did not have ownership of the RX buffer",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			[NO_MEMORY] =
+			"NO_MEMORY: Not enough memory",
+			[DENIED] =
+			"DENIED: Buffer pair already registered",
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno() - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+static int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* Map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+static int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* Map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	log_err("%s\n", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/* FF-A ABIs implementation (U-Boot side) */
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void __weak invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+}
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	log_info("FF-A driver %d.%d\nFF-A framework %d.%d\n",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) {
+		log_info("FF-A versions are compatible\n");
+
+		if (dev) {
+			uc_priv = dev_get_uclass_priv(dev);
+			if (uc_priv)
+				uc_priv->fwk_version = res.a0;
+		}
+
+		return 0;
+	}
+
+	log_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id() - FFA_ID_GET handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		uc_priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		log_debug("FF-A endpoint ID is %u\n", uc_priv->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt() - set the minimum number of pages in each of the RX/TX buffers
+ * @dev: The FF-A bus device
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * Set the minimum number of pages in each of the RX/TX buffers in uc_priv
+ *
+ * Return:
+ *
+ * rxtx_min_pages field contains the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	switch (prop_field) {
+	case RXTX_4K:
+		uc_priv->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		uc_priv->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		uc_priv->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		log_err("RX/TX buffer size not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features_hdlr() - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_FEATURES FF-A function to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers() - free the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Free the RX/TX buffers
+ */
+static void ffa_free_rxtx_buffers(struct udevice *dev)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Freeing FF-A RX/TX buffers\n");
+
+	if (uc_priv->pair.rxbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+	}
+
+	if (uc_priv->pair.txbuf) {
+		free(uc_priv->pair.txbuf);
+		uc_priv->pair.txbuf = NULL;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers() - allocate the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ * The size of the memory allocated is the minimum allowed.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(struct udevice *dev)
+{
+	u64 bytes;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Using %lu 4KB page(s) for FF-A RX/TX buffers size\n",
+		  uc_priv->pair.rxtx_min_pages);
+
+	bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 * Assumption: Memory allocated with memalign is always physically contiguous
+	 */
+
+	uc_priv->pair.rxbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.rxbuf) {
+		log_err("failure to allocate RX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A RX buffer at virtual address %p\n", uc_priv->pair.rxbuf);
+
+	uc_priv->pair.txbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.txbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+		log_err("failure to allocate the TX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A TX buffer at virtual address %p\n", uc_priv->pair.txbuf);
+
+	/* Make sure the buffers are cleared before use */
+	memset(uc_priv->pair.rxbuf, 0, bytes);
+	memset(uc_priv->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers_hdlr() - FFA_RXTX_MAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_MAP FF-A function to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	ret = ffa_alloc_rxtx_buffers(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 * no need to convert from virtual to physical
+	 */
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = map_to_sysmem(uc_priv->pair.txbuf),
+			.a2 = map_to_sysmem(uc_priv->pair.rxbuf),
+			.a3 = uc_priv->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		log_debug("FF-A RX/TX buffers mapped\n");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers(dev);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_UNMAP FF-A function to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	log_debug("unmapping FF-A RX/TX buffers\n");
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers(dev);
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer_hdlr() - FFA_RX_RELEASE handler function
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_RX_RELEASE FF-A function to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical() - check whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * Used by ffa_read_partitions_info to search for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+static bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+				   const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info() - read queried partition data
+ * @dev: The FF-A bus device
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * Read the partitions information returned by the FFA_PARTITION_INFO_GET and saves it in uc_priv
+ *
+ * Return:
+ *
+ * uc_priv is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(struct udevice *dev, u32 count,
+				    struct ffa_partition_uuid *part_uuid)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	if (!count) {
+		log_err("no partition detected\n");
+		return -ENODATA;
+	}
+
+	log_debug("Reading FF-A partitions data from the RX buffer\n");
+
+	if (!part_uuid) {
+		/* Querying information of all partitions */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			log_err("partitions data size exceeds the RX buffer size:\n");
+			log_err("    sizes in bytes: data %llu , RX buffer %llu\n",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		uc_priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO);
+		if (!uc_priv->partitions.descs) {
+			log_err("cannot  allocate partitions data buffer\n");
+			return -ENOMEM;
+		}
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			uc_priv->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			log_debug("FF-A partition ID %x : info cached\n",
+				  uc_priv->partitions.descs[desc_idx].info.id);
+		}
+
+		uc_priv->partitions.count = count;
+
+		log_debug("%d FF-A partition(s) found and cached\n", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		/*
+		 * Search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/* Search the current ID in the cached partitions */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < uc_priv->partitions.count;
+			     cached_desc_idx++) {
+				/* Save the UUID */
+				if (uc_priv->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					uc_priv->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info() - invoke FFA_PARTITION_INFO_GET and save partitions data
+ * @dev: The FF-A bus device
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * Execute the FFA_PARTITION_INFO_GET to query the partitions data.
+ * Then, call ffa_read_partitions_info to save the data in uc_priv.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid);
+			if (ret) {
+				log_err("failed reading SP(s) data , err (%d)\n", ret);
+				ffa_release_rx_buffer_hdlr(dev);
+				return -EINVAL;
+			}
+		}
+
+		/* Return the SP count (when querying using a UUID) */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer_hdlr(dev);
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET FF-A function to query the partition information
+ * from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * If the partition(s) matching the UUID found, the partition(s) information and the
+ * number are returned.
+ * If no partition matching the UUID is found in the cached area, a new FFA_PARTITION_INFO_GET
+ * call is issued.
+ * If not done yet, the UUID is updated in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	u32 i;
+	struct ffa_partition_uuid part_uuid = {0};
+	struct ffa_priv *uc_priv;
+	struct ffa_partition_desc *rx_descs;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs) {
+		log_err("no partition installed\n");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		log_err("no UUID provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_count) {
+		log_err("no count argument provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_descs) {
+		log_err("no info argument provided\n");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		log_err("invalid UUID\n");
+		return -EINVAL;
+	}
+
+	log_debug("Searching FF-A partitions using the provided UUID\n");
+
+	*sp_count = 0;
+	*sp_descs = uc_priv->pair.rxbuf;
+	rx_descs = *sp_descs;
+
+	/* Search in the cached partitions */
+	for (i = 0; i < uc_priv->partitions.count; i++)
+		if (ffa_uuid_are_identical(&uc_priv->partitions.descs[i].sp_uuid,
+					   &part_uuid)) {
+			log_debug("FF-A partition ID %x matches the provided UUID\n",
+				  uc_priv->partitions.descs[i].info.id);
+
+			(*sp_count)++;
+			*rx_descs++ = uc_priv->partitions.descs[i];
+			}
+
+	if (!(*sp_count)) {
+		int ret;
+
+		log_debug("No FF-A partition found. Querying framework ...\n");
+
+		ret = ffa_query_partitions_info(dev, &part_uuid, sp_count);
+
+		if (!ret) {
+			log_debug("Number of FF-A partition(s) matching the UUID: %d\n", *sp_count);
+
+			if (*sp_count)
+				ret = ffa_get_partitions_info_hdlr(dev, uuid_str, sp_count,
+								   sp_descs);
+			else
+				ret = -ENODATA;
+		}
+
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info() - Query and saves all secure partitions data
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_PARTITION_INFO_GET FF-A function to query from secure world
+ * all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in uc_priv
+ * and we keep the UUID field empty (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * Called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(struct udevice *dev)
+{
+	return ffa_query_partitions_info(dev, NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Implement FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u64 req_mode, resp_mode;
+	struct ffa_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* No partition installed */
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs)
+		return -ENODEV;
+
+	if (is_smc64) {
+		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+	} else {
+		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = req_mode,
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == resp_mode) {
+		/* Message sent with response extract the return data */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/* FF-A driver operations (used by clients for communicating with FF-A)*/
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Driver operation for FFA_PARTITION_INFO_GET.
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->partition_info_get)
+		return -ENOSYS;
+
+	return ops->partition_info_get(dev, uuid_str, sp_count, sp_descs);
+}
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Driver operation for FFA_MSG_SEND_DIRECT_{REQ,RESP}.
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->sync_send_receive)
+		return -ENOSYS;
+
+	return ops->sync_send_receive(dev, dst_part_id, msg, is_smc64);
+}
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * @dev: The FF-A bus device
+ *
+ * Driver operation for FFA_RXTX_UNMAP.
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_rxtx_unmap(struct udevice *dev)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->rxtx_unmap)
+		return -ENOSYS;
+
+	return ops->rxtx_unmap(dev);
+}
+
+/**
+ * ffa_do_probe() - probing FF-A framework
+ * @dev:	the FF-A bus device (arm_ffa)
+ *
+ * Probing is triggered on demand by clients searching for the uclass.
+ * At probe level the following actions are done:
+ *	- saving the FF-A framework version in uc_priv
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in uc_priv.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_do_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_endpoint_id(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_cache_partitions_info(dev);
+	if (ret) {
+		ffa_unmap_rxtx_buffers_hdlr(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+UCLASS_DRIVER(ffa) = {
+	.name			= "ffa",
+	.id			= UCLASS_FFA,
+	.pre_probe		= ffa_do_probe,
+	.pre_remove		= ffa_unmap_rxtx_buffers_hdlr,
+	.per_device_auto	= sizeof(struct ffa_priv)
+};
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
new file mode 100644
index 0000000000..68df75bd9e
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -0,0 +1,104 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <linux/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * 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 low level SMC assembly function
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * arm_ffa_discover() - perform FF-A discovery
+ * @dev: The Arm FF-A bus device (arm_ffa)
+ * 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:
+ *
+ * true on success. Otherwise, false.
+ */
+static bool arm_ffa_discover(struct udevice *dev)
+{
+	int ret;
+
+	log_info("Arm FF-A framework discovery\n");
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/**
+ * arm_ffa_is_supported() - FF-A bus discovery callback
+ * @invoke_fn: legacy SMC invoke function (not used)
+ *
+ * Perform FF-A discovery by calling arm_ffa_discover().
+ * Discovery is performed by querying the FF-A framework version from
+ * secure world using the FFA_VERSION ABI.
+ *
+ * The FF-A driver is registered as an SMCCC feature driver. So, features discovery
+ * callbacks are called by the PSCI driver (PSCI device is the SMCCC features
+ * root device).
+ *
+ * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
+ * So, the legacy SMC invocation is not used.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static bool arm_ffa_is_supported(void (*invoke_fn)(ulong a0, ulong a1,
+						   ulong a2, ulong a3,
+						   ulong a4, ulong a5,
+						   ulong a6, ulong a7,
+						   struct arm_smccc_res *res))
+{
+	return arm_ffa_discover(NULL);
+}
+
+/* Arm FF-A driver operations */
+
+static const struct ffa_bus_ops 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,
+};
+
+/* Registering the FF-A driver as an SMCCC feature driver */
+
+ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
+	.driver_name = FFA_DRV_NAME,
+	.is_supported = arm_ffa_is_supported,
+};
+
+/* Declaring the FF-A driver under UCLASS_FFA */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.flags		= DM_REMOVE_OS_PREPARE,
+	.ops		= &ffa_ops,
+};
diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
new file mode 100644
index 0000000000..4338f9c9b1
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
@@ -0,0 +1,14 @@
+/* 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/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..db9b1be995
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,213 @@
+/* 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 __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
+ * @a1-4:	32-bit words access to the UUID data
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct ffa_send_direct_data {
+	ulong data0; /* w3/x3 */
+	ulong data1; /* w4/x4 */
+	ulong data2; /* w5/x5 */
+	ulong data3; /* w6/x6 */
+	ulong data4; /* w7/x7 */
+};
+
+struct udevice;
+
+/**
+ * struct ffa_bus_ops - Operations for FF-A
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
+				  u32 *sp_count, struct ffa_partition_desc **sp_descs);
+	int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg,
+				 bool is_smc64);
+	int (*rxtx_unmap)(struct udevice *dev);
+};
+
+#define ffa_get_ops(dev)        ((struct ffa_bus_ops *)(dev)->driver->ops)
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ */
+int ffa_rxtx_unmap(struct udevice *dev);
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The arm_ffa bus device
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev);
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The arm_ffa bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+struct ffa_priv;
+
+/**
+ * ffa_set_smc_conduit() - Set the SMC conduit
+ * @dev: The FF-A bus device
+ *
+ * Selects the SMC conduit by setting the FF-A ABI invoke function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_set_smc_conduit(struct udevice *dev);
+
+#endif
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
new file mode 100644
index 0000000000..d564c33c64
--- /dev/null
+++ b/include/arm_ffa_priv.h
@@ -0,0 +1,246 @@
+/* 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 __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <mapmem.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+
+/* This header is exclusively used by the FF-A Uclass and FF-A driver(s) */
+
+/* Arm FF-A driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* The FF-A SMC function definitions */
+
+#if CONFIG_IS_ENABLED(SANDBOX)
+
+/* Providing Arm SMCCC declarations to sandbox */
+
+/**
+ * struct sandbox_smccc_1_2_regs - emulated SMC call arguments or results
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct sandbox_smccc_1_2_regs {
+	ulong a0;
+	ulong a1;
+	ulong a2;
+	ulong a3;
+	ulong a4;
+	ulong a5;
+	ulong a6;
+	ulong a7;
+	ulong a8;
+	ulong a9;
+	ulong a10;
+	ulong a11;
+	ulong a12;
+	ulong a13;
+	ulong a14;
+	ulong a15;
+	ulong a16;
+	ulong a17;
+};
+
+typedef struct sandbox_smccc_1_2_regs ffa_value_t;
+
+#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))
+
+#else
+/* CONFIG_ARM64 */
+#include <linux/arm-smccc.h>
+typedef struct arm_smccc_1_2_regs ffa_value_t;
+#endif
+
+/* Defining the function pointer type for the function executing the FF-A ABIs */
+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)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR                 = 0x60,
+	FFA_SUCCESS               = 0x61,
+	FFA_INTERRUPT             = 0x62,
+	FFA_VERSION               = 0x63,
+	FFA_FEATURES              = 0x64,
+	FFA_RX_RELEASE            = 0x65,
+	FFA_RXTX_MAP              = 0x66,
+	FFA_RXTX_UNMAP            = 0x67,
+	FFA_PARTITION_INFO_GET    = 0x68,
+	FFA_ID_GET                = 0x69,
+	FFA_RUN                   = 0x6d,
+	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
+	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
+
+	/* To be updated when adding new FFA IDs */
+	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
+	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
+};
+
+enum ffa_abi_errcode {
+	NOT_SUPPORTED = 1,
+	INVALID_PARAMETERS,
+	NO_MEMORY,
+	BUSY,
+	INTERRUPTED,
+	DENIED,
+	RETRY,
+	ABORTED,
+	MAX_NUMBER_FFA_ERR
+};
+
+extern int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR];
+
+/* Container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Hosts the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	void *rxbuf; /* Virtual address returned by memalign */
+	void *txbuf; /* Virtual address returned by memalign */
+	size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */
+};
+
+struct ffa_partition_desc;
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * Contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* Virtual address */
+};
+
+/**
+ * struct ffa_priv - the driver private data structure
+ *
+ * @fwk_version:	FF-A framework version
+ * @emul:	FF-A sandbox emulator
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ *
+ * The device private data structure containing all the
+ * data read from secure world.
+ */
+struct ffa_priv {
+	u32 fwk_version;
+	struct udevice *emul;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+};
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev);
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 307ad6931c..3c6af2e3d2 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,11 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -57,6 +62,7 @@ enum uclass_id {
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_EXTCON,		/* External Connector Class */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v16 05/10] arm_ffa: introduce armffa command
  2023-07-26  9:44                                                                                                                                               ` [PATCH v16 " Abdellatif El Khlifi
                                                                                                                                                                   ` (3 preceding siblings ...)
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-07-26  9:44                                                                                                                                                 ` Abdellatif El Khlifi
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
                                                                                                                                                                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-26  9:44 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, u-boot, Simon Glass, Ilias Apalodimas,
	Jens Wiklander, Heinrich Schuchardt

Provide armffa command showcasing the use of the U-Boot FF-A support

armffa is a command showcasing how to invoke FF-A operations.
This provides a guidance to the client developers on how to
call the FF-A bus interfaces. The command also allows to gather secure
partitions information and ping these  partitions. The command is also
helpful in testing the communication with secure partitions.

For more details please refer to the command documentation [1].

[1]: doc/usage/cmd/armffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v15:

Simon:

* armffa.c : integrate PHYS_ADDR_LN

v14:

Ilias:

* address nits
* in do_ffa_ping() reject the SP ID if it's 0
* use PHYS_ADDR_LN in formatting the physical addresses

v12:

* add subcommands argument checks
* usage documentation: update command return codes
* remove calloc when querying SPs
* address nits

v11:

* use U_BOOT_CMD_WITH_SUBCMDS
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* address nits

v9:

* remove manual FF-A discovery and use DM
* use DM class APIs to probe and interact with the FF-A bus
* add doc/usage/cmd/armffa.rst

v8:

* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* adapt do_ffa_dev_list() following the recent update on
  uclass_first_device/uclass_next_device functions (they return void now)
* set armffa command to use 64-bit direct messaging

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

MAINTAINERS                      |   2 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   1 +
 cmd/armffa.c                     | 202 +++++++++++++++++++++++++++++++
 doc/arch/arm64.ffa.rst           |   7 ++
 doc/usage/cmd/armffa.rst         |  94 ++++++++++++++
 doc/usage/index.rst              |   1 +
 drivers/firmware/arm-ffa/Kconfig |   1 +
 8 files changed, 318 insertions(+)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/usage/cmd/armffa.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 4fd5768de0..7bfac78e59 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,7 +269,9 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+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
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 02e54f1e50..79b4f8367a 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -935,6 +935,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the FF-A support
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index 6c37521b4e..7d20a85a46 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,7 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_2048) += 2048.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..7e6eafc03a
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,202 @@
+// 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 <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+#include <asm/io.h>
+
+/* Select the right physical address formatting according to the platform */
+#ifdef CONFIG_PHYS_64BIT
+#define PhysAddrLength "ll"
+#else
+#define PhysAddrLength ""
+#endif
+#define PHYS_ADDR_LN "%" PhysAddrLength "x"
+
+/**
+ * ffa_get_dev() - Return the FF-A device
+ * @devp:	pointer to the FF-A device
+ *
+ * Search for the FF-A device.
+ *
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_dev(struct udevice **devp)
+{
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, devp);
+	if (ret) {
+		log_err("Cannot find FF-A bus device\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * do_ffa_getpart() - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query a secure partition information. The secure partition UUID is provided
+ * as an argument. The function uses the arm_ffa driver
+ * partition_info_get operation which implements FFA_PARTITION_INFO_GET
+ * ABI to retrieve the data. The input UUID string is expected to be in big
+ * endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	u32 i;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+
+	ret = ffa_partition_info_get(dev, argv[1], &count, &descs);
+	if (ret) {
+		log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	/* SPs found , show the partition information */
+	for (i = 0; i < count ; i++) {
+		log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
+			 descs[i].info.id,
+			 descs[i].info.exec_ctxt,
+			 descs[i].info.properties);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_ffa_ping() - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Send data to a secure partition. The secure partition UUID is provided
+ * as an argument. Use the arm_ffa driver sync_send_receive operation
+ * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	part_id = strtoul(argv[1], NULL, 16);
+	if (!part_id) {
+		log_err("Partition ID can not be 0\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	if (!ret) {
+		u8 cnt;
+
+		log_info("SP response:\n[LSB]\n");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			log_info("%llx\n", ((u64 *)&msg)[cnt]);
+		return CMD_RET_SUCCESS;
+	}
+
+	log_err("Sending direct request error (%d)\n", ret);
+	return CMD_RET_FAILURE;
+}
+
+/**
+ *do_ffa_devlist() - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query the device belonging to the UCLASS_FFA
+ * class.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",
+		 dev->name,
+		 map_to_sysmem(dev),
+		 dev->driver->name,
+		 map_to_sysmem(dev->driver->ops));
+
+	return CMD_RET_SUCCESS;
+}
+
+static char armffa_help_text[] =
+	"getpart <partition UUID>\n"
+	"       - lists the partition(s) info\n"
+	"ping <partition ID>\n"
+	"       - sends a data pattern to the specified partition\n"
+	"devlist\n"
+	"       - displays information about the FF-A device/driver\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
+			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
+			U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping),
+			U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist));
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 4f817f053c..aefd527447 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -205,6 +205,13 @@ The following features are provided:
 
 - FF-A bus can be compiled and used without EFI
 
+The armffa command
+-----------------------------------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke the driver operations.
+
+Please refer the command documentation at :doc:`../usage/cmd/armffa`
+
 Example of boot logs with FF-A enabled
 --------------------------------------
 
diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
new file mode 100644
index 0000000000..13fa90c129
--- /dev/null
+++ b/doc/usage/cmd/armffa.rst
@@ -0,0 +1,94 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+
+armffa command
+==============
+
+Synopsis
+--------
+
+::
+
+   armffa [sub-command] [arguments]
+
+   sub-commands:
+
+        getpart [partition UUID]
+
+            lists the partition(s) info
+
+        ping [partition ID]
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays information about the FF-A device/driver
+
+Description
+-----------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
+
+The command also allows to gather secure partitions information and ping these  partitions.
+
+The command is also helpful in testing the communication with secure partitions.
+
+Example
+-------
+
+The following examples are run on Corstone-1000 platform.
+
+* ping
+
+::
+
+   corstone1000# armffa ping 0x8003
+   SP response:
+   [LSB]
+   fffffffe
+   0
+   0
+   0
+   0
+
+* ping (failure case)
+
+::
+
+   corstone1000# armffa ping 0
+   Sending direct request error (-22)
+
+* getpart
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
+   Partition: id = 8003 , exec_ctxt 1 , properties 3
+
+* getpart (failure case)
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221
+   INVALID_PARAMETERS: Unrecognized UUID
+   Failure in querying partitions count (error code: -22)
+
+* devlist
+
+::
+
+   corstone1000# armffa devlist
+   device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98
+
+Configuration
+-------------
+
+The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
+
+Return value
+------------
+
+The return value $? is 0 (true) on success, 1 (false) on failure.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 388e59f173..e462de2806 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -22,6 +22,7 @@ Shell commands
 
    cmd/acpi
    cmd/addrmap
+   cmd/armffa
    cmd/askenv
    cmd/base
    cmd/bdinfo
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index 9200c8028b..a7d5392859 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
 	depends on DM && ARM64
 	select ARM_SMCCC
 	select ARM_SMCCC_FEATURES
+	imply CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v16 06/10] arm_ffa: introduce sandbox FF-A support
  2023-07-26  9:44                                                                                                                                               ` [PATCH v16 " Abdellatif El Khlifi
                                                                                                                                                                   ` (4 preceding siblings ...)
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-07-26  9:44                                                                                                                                                 ` Abdellatif El Khlifi
  2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                                                                                                                                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-26  9:44 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, u-boot, Simon Glass, Ilias Apalodimas,
	Jens Wiklander, Heinrich Schuchardt

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>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove reparenting by making the emulator parent of the FF-A device in the DT
* add invoke_ffa_fn()
* address nits

v11:

* rename ffa_try_discovery() to sandbox_ffa_discover()
* rename sandbox_ffa_query_core_state() to sandbox_query_ffa_emul_state()
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device

v10:

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

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

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

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

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

v1: introduce the sandbox driver

MAINTAINERS                                   |   3 +-
 arch/sandbox/dts/sandbox.dtsi                 |   9 +
 arch/sandbox/dts/test.dts                     |   8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |  72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        | 121 +++
 configs/sandbox64_defconfig                   |   1 +
 configs/sandbox_defconfig                     |   1 +
 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, 1081 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 7bfac78e59..7f4efb6358 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..96b5404991 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1820,6 +1820,14 @@
 	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..72ea3d21ab 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -260,3 +260,4 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 1ec44d5b33..8269bec879 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -344,3 +344,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 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


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v16 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA
  2023-07-26  9:44                                                                                                                                               ` [PATCH v16 " Abdellatif El Khlifi
                                                                                                                                                                   ` (5 preceding siblings ...)
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
@ 2023-07-26  9:45                                                                                                                                                 ` Abdellatif El Khlifi
  2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                                                                                                                                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-26  9:45 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, u-boot, Simon Glass, Ilias Apalodimas,
	Jens Wiklander, Heinrich Schuchardt

Add functional test cases for the FF-A support

These tests rely on the FF-A sandbox emulator and FF-A
sandbox driver which help in inspecting the FF-A communication.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove use of dscvry_info
* drop use of calloc when querying SPs
* address nits

v11:

* drop unmapping test (taken care of by the DM when removing the device)
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT
* address nits

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

v8:

  * update partition_info_get() second argument to be an SP count
  * pass NULL device pointer to the FF-A bus discovery and operations

v7: set the tests to use 64-bit direct messaging

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

v1: introduce sandbox tests

MAINTAINERS            |   1 +
 doc/arch/arm64.ffa.rst |   1 +
 test/dm/Makefile       |   3 +-
 test/dm/ffa.c          | 261 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 265 insertions(+), 1 deletion(-)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7f4efb6358..a79e3a8429 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index b7c754fa3d..325fb80346 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -37,6 +37,7 @@ The U-Boot FF-A support provides the following parts:
   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.
+- Sandbox FF-A test cases.
 
 FF-A and SMC specifications
 -------------------------------------------
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 3799b1ae8f..7ed00733c1 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
-# Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -92,6 +92,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..6912666bb4
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <console.h>
+#include <dm.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <asm/sandbox_arm_ffa_priv.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Functional tests for the UCLASS_FFA */
+
+static int check_fwk_version(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	struct ffa_sandbox_data func_data;
+	u32 fwk_version = 0;
+
+	func_data.data0 = &fwk_version;
+	func_data.data0_size = sizeof(fwk_version);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_VERSION, &func_data));
+	ut_asserteq(uc_priv->fwk_version, fwk_version);
+
+	return 0;
+}
+
+static int check_endpoint_id(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_asserteq(0, uc_priv->id);
+
+	return 0;
+}
+
+static int check_rxtxbuf(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assertnonnull(uc_priv->pair.rxbuf);
+	ut_assertnonnull(uc_priv->pair.txbuf);
+
+	return 0;
+}
+
+static int check_features(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assert(uc_priv->pair.rxtx_min_pages == RXTX_4K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_16K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_64K);
+
+	return 0;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+		ut_asserteq(1, rxbuf_mapped);
+		break;
+	case FFA_RXTX_UNMAP:
+		ut_asserteq(0, rxbuf_mapped);
+		break;
+	default:
+		ut_assert(false);
+	}
+
+	return 0;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	ut_asserteq(0, rxbuf_owned);
+
+	return 0;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg;
+	u8 cnt;
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]);
+
+	return 0;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct unit_test_state *uts)
+{
+	struct ffa_partition_desc *descs;
+	u32 count, i, j, valid_sps = 0;
+	struct udevice *dev;
+	struct ffa_sandbox_data func_data;
+	struct ffa_partitions *partitions;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get from the driver the count and information of the SPs matching the UUID */
+	ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, &descs));
+
+	/* Make sure the count is correct */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+
+	/* SPs found , verify the partitions information */
+
+	func_data.data0 = &partitions;
+	func_data.data0_size = sizeof(struct ffa_partitions *);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_PARTITION_INFO_GET, &func_data));
+
+	for (i = 0; i < count ; i++) {
+		for (j = 0;
+		     j < partitions->count;
+		     j++) {
+			if (descs[i].info.id ==
+			   partitions->descs[j].info.id) {
+				valid_sps++;
+				ut_asserteq_mem(&descs[i],
+						&partitions->descs[j],
+						sizeof(struct ffa_partition_desc));
+				/* Send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(descs[i].info.id, uts);
+			}
+		}
+	}
+
+	/* Verify expected partitions found in the emulated secure world */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, valid_sps);
+
+	return 0;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	struct ffa_sandbox_data func_data;
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	struct udevice *dev;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Test FFA_VERSION */
+	check_fwk_version(uc_priv, uts);
+
+	/* Test FFA_ID_GET */
+	check_endpoint_id(uc_priv, uts);
+
+	/* Test FFA_FEATURES */
+	check_features(uc_priv, uts);
+
+	/*  Test RX/TX buffers */
+	check_rxtxbuf(uc_priv, uts);
+
+	/* Test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	sandbox_query_ffa_emul_state(FFA_RXTX_MAP, &func_data);
+	check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc1_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data);
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc2_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data));
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg;
+	int ret;
+	u32 count;
+	u16 part_id = 0;
+	struct udevice *dev;
+	struct ffa_partition_desc *descs = NULL;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Query partitions count using  invalid arguments */
+	ret = ffa_partition_info_get(dev, NULL, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, NULL);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID  string */
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid_str, &count, &descs);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, &descs);
+	ut_asserteq(0, count);
+
+	/* Query partitions data using a valid UUID */
+	count = 0;
+	ut_assertok(ffa_partition_info_get(dev, valid_svc_uuid, &count, &descs));
+	/* Make sure partitions are detected */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+	ut_assertnonnull(descs);
+
+	/* Send data to an invalid partition */
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Send data to a valid partition */
+	part_id = uc_priv->partitions.descs[0].info.id;
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v16 08/10] arm_ffa: introduce armffa command Sandbox test
  2023-07-26  9:44                                                                                                                                               ` [PATCH v16 " Abdellatif El Khlifi
                                                                                                                                                                   ` (6 preceding siblings ...)
  2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-07-26  9:45                                                                                                                                                 ` Abdellatif El Khlifi
  2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
  2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-26  9:45 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, u-boot, Simon Glass, Ilias Apalodimas,
	Jens Wiklander

Add Sandbox test for the armffa command

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v12:

* address nits

v10:

* replace CMD_RET_SUCCESS with 0
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT

v9: align the test with FF-A discovery through DM

v4: drop use of helper APIs

v1: introduce armffa command sandbox test

MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a79e3a8429..bd3dba3d95 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index a3cf983739..6e3d7e919e 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -24,6 +25,7 @@ obj-$(CONFIG_CMD_SEAMA) += seama.o
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_CMD_READ) += rw.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o
 endif
 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
 obj-$(CONFIG_CMD_WGET) += wget.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..9a44a397e8
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * 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 <string.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	/* armffa ping <ID> */
+	ut_assertok(run_commandf("armffa ping 0x%x", SANDBOX_SP1_ID));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return 0;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-26  9:44                                                                                                                                               ` [PATCH v16 " Abdellatif El Khlifi
                                                                                                                                                                   ` (7 preceding siblings ...)
  2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2023-07-26  9:45                                                                                                                                                 ` Abdellatif El Khlifi
  2023-07-26 19:39                                                                                                                                                   ` Tom Rini
                                                                                                                                                                     ` (2 more replies)
  2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  9 siblings, 3 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-26  9:45 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, u-boot, Gowtham Suresh Kumar,
	Simon Glass, Ilias Apalodimas, Jens Wiklander

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

MM communication protocol supports FF-A 64-bit direct messaging.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v16:

* lib/efi_loader/Kconfig:
   rather than automatically selecting OPTEE and ARM_FFA_TRANSPORT configs by
   EFI_MM_COMM_TEE, set them as dependencies (Otherwise FF-A will be automatically
   enabled for boards that don't need it).

v15:

Simon:

* replace FFA_SHARED_MM_BUFFER_* defines with configs

v14:

Ilias:

* drop truncating var_payload->size when using FF-A
* map the MM SP return codes to errnos

v13:

* remove FF-A and Optee ifdefs

v12:

* drop use of calloc when querying SPs
* address nits

v11:

* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* addressing nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* addressing nits

v9: align how FF-A is used with FF-A discovery through DM

v8:

* isolate the compilation choices between FF-A and OP-TEE
* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make mm_sp_svc_uuid static
* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
* improve use of unmap_sysmem() in ffa_mm_communicate()

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

include/mm_communication.h        |  13 ++
 lib/efi_loader/Kconfig            |  44 ++++-
 lib/efi_loader/efi_variable_tee.c | 257 +++++++++++++++++++++++++++++-
 3 files changed, 307 insertions(+), 7 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..f17847583b 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,9 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *    Authors:
+ *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +16,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
@@ -248,4 +254,11 @@ struct smm_variable_var_check_property {
 	u16                       name[];
 };
 
+/* supported MM transports */
+enum mm_comms_select {
+	MM_COMMS_UNDEFINED,
+	MM_COMMS_FFA,
+	MM_COMMS_OPTEE
+};
+
 #endif /* _MM_COMMUNICATION_H_ */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c5835e6ef6..8fbadb9201 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	depends on OPTEE && ARM_FFA_TRANSPORT
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
+config FFA_SHARED_MM_BUF_SIZE
+	int "Memory size of the shared MM communication buffer"
+	default 0
+	depends on EFI_MM_COMM_TEE
+	help
+	  This defines the size in bytes of the memory area reserved for the shared
+	  buffer used for communication between the MM feature in U-Boot and
+	  the MM SP in secure world.
+	  The size of the memory region must be a multiple of the size of the maximum
+	  translation granule size that is specified in the ID_AA64MMFR0_EL1 System register.
+	  It is assumed that the MM SP knows the size of the shared MM communication buffer.
+
+config FFA_SHARED_MM_BUF_OFFSET
+	int "Data offset in the shared MM communication buffer"
+	default 0
+	depends on EFI_MM_COMM_TEE
+	help
+	  This defines the offset in bytes of the data read or written to in the shared
+	  buffer by the MM SP.
+
+config FFA_SHARED_MM_BUF_ADDR
+	hex "Define the address of the shared MM communication buffer"
+	default 0x0
+	depends on EFI_MM_COMM_TEE
+	help
+	  This defines the address of the shared MM communication buffer
+	  used for communication between the MM feature in U-Boot and
+	  the MM SP in secure world.
+	  It is assumed that the MM SP knows the address of the shared MM communication buffer.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..5137b871ea 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,17 +4,34 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  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 <cpu_func.h>
+#include <dm.h>
 #include <efi.h>
 #include <efi_api.h>
 #include <efi_loader.h>
 #include <efi_variable.h>
-#include <tee.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <mm_communication.h>
+#include <tee.h>
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+#define MM_NOT_SUPPORTED (-1)
+#define MM_INVALID_PARAMETER (-2)
+#define MM_DENIED (-3)
+#define MM_NO_MEMORY (-5)
 
+static const char *mm_sp_svc_uuid = MM_SP_UUID;
+static u16 mm_sp_id;
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -145,16 +162,241 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 }
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notify the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
+		return ret;
+	}
+
+	msg.data0 = CONFIG_FFA_SHARED_MM_BUF_OFFSET; /* x3 */
+
+	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
+	if (ret)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	switch (sp_event_ret) {
+	case MM_SUCCESS:
+		ret = 0;
+		break;
+	case MM_NOT_SUPPORTED:
+		ret = -EINVAL;
+		break;
+	case MM_INVALID_PARAMETER:
+		ret = -EPERM;
+		break;
+	case MM_DENIED:
+		ret = -EACCES;
+		break;
+	case MM_NO_MEMORY:
+		ret = -EBUSY;
+		break;
+	default:
+		ret = -EACCES;
+	}
+
+	return ret;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
+		return ret;
+	}
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, &descs);
+	if (ret) {
+		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
+		return ret;
+	}
+
+	/* MM SPs found , use the first one */
+
+	mm_sp_id = descs[0].info.id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	return 0;
+}
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	efi_status_t efi_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()) {
+		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > CONFIG_FFA_SHARED_MM_BUF_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = map_sysmem((phys_addr_t)CONFIG_FFA_SHARED_MM_BUF_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+
+	switch (ffa_ret) {
+	case 0: {
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		efi_ret = EFI_SUCCESS;
+		break;
+	}
+	case -EINVAL:
+		efi_ret = EFI_DEVICE_ERROR;
+		break;
+	case -EPERM:
+		efi_ret = EFI_INVALID_PARAMETER;
+		break;
+	case -EACCES:
+		efi_ret = EFI_ACCESS_DENIED;
+		break;
+	case -EBUSY:
+		efi_ret = EFI_OUT_OF_RESOURCES;
+		break;
+	default:
+		efi_ret = EFI_ACCESS_DENIED;
+	}
+
+	unmap_sysmem(virt_shared_buf);
+	return efi_ret;
+}
+
+/**
+ * get_mm_comms() - detect the available MM transport
+ *
+ * Make sure the FF-A bus is probed successfully
+ * which means FF-A communication with secure world works and ready
+ * for use.
+ *
+ * If FF-A bus is not ready, use OPTEE comms.
+ *
+ * Return:
+ *
+ * MM_COMMS_FFA or MM_COMMS_OPTEE
+ */
+static enum mm_comms_select get_mm_comms(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, trying Optee comms\n");
+		return MM_COMMS_OPTEE;
+	}
+
+	return MM_COMMS_FFA;
+}
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 {
 	efi_status_t ret;
+	enum mm_comms_select mm_comms;
 	struct efi_mm_communicate_header *mm_hdr;
 	struct smm_variable_communicate_header *var_hdr;
 
@@ -162,7 +404,12 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+	mm_comms = get_mm_comms();
+	if (mm_comms == MM_COMMS_FFA)
+		ret = ffa_mm_communicate(comm_buf, dsize);
+	else
+		ret = optee_mm_communicate(comm_buf, dsize);
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -697,7 +944,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v16 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2023-07-26  9:44                                                                                                                                               ` [PATCH v16 " Abdellatif El Khlifi
                                                                                                                                                                   ` (8 preceding siblings ...)
  2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-07-26  9:45                                                                                                                                                 ` Abdellatif El Khlifi
  2023-07-26 16:06                                                                                                                                                   ` Tom Rini
  9 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-26  9:45 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, nd, u-boot, Simon Glass, Ilias Apalodimas,
	Jens Wiklander

turn on EFI MM communication

On Corstone-1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

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>

---

Changelog:
===============

v16:

* configs/corstone1000_defconfig:
   enable MM communication by setting the configs: ARM_FFA_TRANSPORT, OPTEE, TEE

v15:

Simon:

* use CONFIG_FFA_SHARED_MM_BUF_* configs in place of FFA_SHARED_MM_BUFFER_*

v13:

* remove FF-A config in the defconfig
   (because it's enabled automatically by CONFIG_EFI_MM_COMM_TEE)

v9:

* update copyright string

v8:

* drop OP-TEE configs from Corstone-1000 defconfig

v7:

* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
  FFA_SHARED_MM_BUFFER_OFFSET
* update FFA_SHARED_MM_BUFFER_ADDR value

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

configs/corstone1000_defconfig | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index a8a79fd105..fa9f9e4f07 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -65,3 +65,10 @@ CONFIG_EFI_CAPSULE_ON_DISK=y
 CONFIG_EFI_IGNORE_OSINDICATIONS=y
 CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_ERRNO_STR=y
+CONFIG_ARM_FFA_TRANSPORT=y
+CONFIG_OPTEE=y
+CONFIG_TEE=y
+CONFIG_EFI_MM_COMM_TEE=y
+CONFIG_FFA_SHARED_MM_BUF_SIZE=4096
+CONFIG_FFA_SHARED_MM_BUF_OFFSET=0
+CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v16 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
@ 2023-07-26 16:06                                                                                                                                                   ` Tom Rini
  2023-07-27 16:07                                                                                                                                                     ` [PATCH v17 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-07-26 16:06 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: nd, u-boot, Simon Glass, Ilias Apalodimas, Jens Wiklander

[-- Attachment #1: Type: text/plain, Size: 1253 bytes --]

On Wed, Jul 26, 2023 at 10:45:03AM +0100, Abdellatif El Khlifi wrote:

> turn on EFI MM communication
> 
> On Corstone-1000 platform MM communication between u-boot
> and the secure world (Optee) is done using the FF-A bus.
> 
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
[snip]
> diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
> index a8a79fd105..fa9f9e4f07 100644
> --- a/configs/corstone1000_defconfig
> +++ b/configs/corstone1000_defconfig
> @@ -65,3 +65,10 @@ CONFIG_EFI_CAPSULE_ON_DISK=y
>  CONFIG_EFI_IGNORE_OSINDICATIONS=y
>  CONFIG_FWU_MULTI_BANK_UPDATE=y
>  CONFIG_ERRNO_STR=y
> +CONFIG_ARM_FFA_TRANSPORT=y
> +CONFIG_OPTEE=y
> +CONFIG_TEE=y
> +CONFIG_EFI_MM_COMM_TEE=y
> +CONFIG_FFA_SHARED_MM_BUF_SIZE=4096
> +CONFIG_FFA_SHARED_MM_BUF_OFFSET=0
> +CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000

Not a nak and unless there's other comments I'll simply fix this up, but
you cannot just add options to the bottom of the configs.  These are
"defconfig" files like the kernel so for something like this you would
do (and I did locally before throwing this at CI now):
$ make corstone1000_defconfig savedefconfig
$ mv defconfig configs/corstone1000_defconfig

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-07-26 19:39                                                                                                                                                   ` Tom Rini
  2023-07-27  9:34                                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-27  9:58                                                                                                                                                   ` Ilias Apalodimas
  2023-07-27 11:27                                                                                                                                                   ` Ilias Apalodimas
  2 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-07-26 19:39 UTC (permalink / raw)
  To: Abdellatif El Khlifi, Meenakshi Aggarwal, Priyanka Jain, Wasim Khan
  Cc: nd, u-boot, Gowtham Suresh Kumar, Simon Glass, Ilias Apalodimas,
	Jens Wiklander

[-- Attachment #1: Type: text/plain, Size: 1758 bytes --]

On Wed, Jul 26, 2023 at 10:45:02AM +0100, Abdellatif El Khlifi wrote:

> Add MM communication support using FF-A transport
> 
> This feature allows accessing MM partitions services through
> EFI MM communication protocol. MM partitions such as StandAlonneMM
> or smm-gateway secure partitions which reside in secure world.
> 
> An MM shared buffer and a door bell event are used to exchange
> the data.
> 
> The data is used by EFI services such as GetVariable()/SetVariable()
> and copied from the communication buffer to the MM shared buffer.
> 
> The secure partition is notified about availability of data in the
> MM shared buffer by an FF-A message (door bell).
> 
> On such event, MM SP can read the data and updates the MM shared
> buffer with the response data.
> 
> The response data is copied back to the communication buffer and
> consumed by the EFI subsystem.
> 
> MM communication protocol supports FF-A 64-bit direct messaging.
> 
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Cc: Jens Wiklander <jens.wiklander@linaro.org>

So, at this point in the series we impact lx2160ardb_tfa_stmm which is
the only config in the tree prior to this series that sets
CONFIG_EFI_MM_COMM_TEE. I'm not going to block this series[1] on
updating lx2160ardb_tfa_stmm as well, but I do want to make sure the
maintainers there are aware and can update the config to support the
current state of this technology.

[1]: https://patchwork.ozlabs.org/project/uboot/list/?series=365876&state=*
-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 2/6] arm_ffa: introduce armffa command
  2022-03-29 15:16 ` [PATCH 2/6] arm_ffa: introduce armffa command abdellatif.elkhlifi
@ 2023-07-27  5:51   ` Heinrich Schuchardt
  2023-07-27  9:00     ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Heinrich Schuchardt @ 2023-07-27  5:51 UTC (permalink / raw)
  To: abdellatif.elkhlifi; +Cc: nd, trini, Ilias Apalodimas, u-boot

On 3/29/22 17:16, abdellatif.elkhlifi@arm.com wrote:
> From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>
> Provide armffa command showcasing the use of the FF-A driver
>
> The armffa command allows to query secure partitions data from
> the secure world and exchanging messages with the partitions.
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Cc: Tom Rini <trini@konsulko.com>
> ---
>   MAINTAINERS             |   1 +
>   cmd/Kconfig             |  10 ++
>   cmd/Makefile            |   2 +
>   cmd/armffa.c            | 266 ++++++++++++++++++++++++++++++++++++++++
>   drivers/arm-ffa/Kconfig |   1 +

We want to have all commands to be documented in /doc/usage/cmd/.

Could you, please, provide the missing /doc/usage/cmd/armffa.rst file.

Best regards

Heinrich

>   5 files changed, 280 insertions(+)
>   create mode 100644 cmd/armffa.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c5b608eb60..50ccd6a7ba 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -235,6 +235,7 @@ F:	include/configs/turris_*.h
>   ARM FF-A
>   M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   S:	Maintained
> +F:	cmd/armffa.c
>   F:	drivers/arm-ffa/
>   F:	include/arm_ffa.h
>   F:	include/arm_ffa_helper.h
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 79219bcb74..de5bea1404 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -813,6 +813,16 @@ endmenu
>
>   menu "Device access commands"
>
> +config CMD_ARMFFA
> +	bool "Arm FF-A test command"
> +	depends on ARM_FFA_TRANSPORT
> +	help
> +	  Provides a test command for the Arm FF-A driver
> +	  supported options:
> +		- Listing the partition(s) info
> +		- Sending a data pattern to the specified partition
> +		- Displaying the arm_ffa device info
> +
>   config CMD_ARMFLASH
>   	#depends on FLASH_CFI_DRIVER
>   	bool "armflash"
> diff --git a/cmd/Makefile b/cmd/Makefile
> index ede634d731..2905ce63cf 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -12,6 +12,8 @@ obj-y += panic.o
>   obj-y += version.o
>
>   # command
> +
> +obj-$(CONFIG_CMD_ARMFFA) += armffa.o
>   obj-$(CONFIG_CMD_ACPI) += acpi.o
>   obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
>   obj-$(CONFIG_CMD_AES) += aes.o
> diff --git a/cmd/armffa.c b/cmd/armffa.c
> new file mode 100644
> index 0000000000..fcfc3a06bd
> --- /dev/null
> +++ b/cmd/armffa.c
> @@ -0,0 +1,266 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2022 ARM Limited
> + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> + */
> +
> +#include <arm_ffa_helper.h>
> +#include <asm/io.h>
> +#include <common.h>
> +#include <command.h>
> +#include <dm.h>
> +#include <mapmem.h>
> +#include <stdlib.h>
> +
> +/**
> + * do_ffa_get_singular_partition_info - implementation of the getpart subcommand
> + * @cmdtp:		Command Table
> + * @flag:		flags
> + * @argc:		number of arguments
> + * @argv:		arguments
> + *
> + * This function queries the secure partition information which the UUID is provided
> + * as an argument. The function uses the arm_ffa driver helper function
> + * to retrieve the data.
> + * The input UUID string is expected to be in big endian format.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +static int do_ffa_get_singular_partition_info(struct cmd_tbl *cmdtp, int flag, int argc,
> +					      char *const argv[])
> +{
> +	struct ffa_interface_data func_data = {0};
> +	u32 count = 0;
> +	int ret;
> +	union ffa_partition_uuid service_uuid = {0};
> +	struct ffa_partition_info *parts_info;
> +	u32 info_idx;
> +
> +	if (argc != 1)
> +		return -EINVAL;
> +
> +	if (ffa_uuid_str_to_bin(argv[0], (unsigned char *)&service_uuid)) {
> +		ffa_err("Invalid UUID");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * get from the driver the count of the SPs matching the UUID
> +	 */
> +	func_data.data0_size = sizeof(service_uuid);
> +	func_data.data0 = &service_uuid;
> +	func_data.data1_size = sizeof(count);
> +	func_data.data1 = &count;
> +
> +	ret = ffa_helper_get_partitions_info(&func_data);
> +	if (ret != FFA_ERR_STAT_SUCCESS) {
> +		ffa_err("Failure in querying partitions count (error code: %d)", ret);
> +		return ret;
> +	}
> +
> +	if (!count) {
> +		ffa_info("No secure partition found");
> +		return ret;
> +	}
> +
> +	/*
> +	 * pre-allocate a buffer to be filled by the driver
> +	 * with	 ffa_partition_info structs
> +	 */
> +
> +	parts_info = calloc(count, sizeof(struct ffa_partition_info));
> +	if (!parts_info)
> +		return -EINVAL;
> +
> +	ffa_info("Pre-allocating %d partition(s) info structures", count);
> +
> +	func_data.data1_size = count * sizeof(struct ffa_partition_info);
> +	func_data.data1 = parts_info;
> +
> +	/*
> +	 * ask the driver to fill the buffer with the SPs info
> +	 */
> +	ret = ffa_helper_get_partitions_info(&func_data);
> +	if (ret != FFA_ERR_STAT_SUCCESS) {
> +		ffa_err("Failure in querying partition(s) info (error code: %d)", ret);
> +		free(parts_info);
> +		return ret;
> +	}
> +
> +	/*
> +	 * SPs found , show the partition information
> +	 */
> +	for (info_idx = 0; info_idx < count ; info_idx++) {
> +		ffa_info("Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x",
> +			 parts_info[info_idx].id,
> +			 parts_info[info_idx].exec_ctxt,
> +			 parts_info[info_idx].properties);
> +	}
> +
> +	free(parts_info);
> +
> +	return 0;
> +}
> +
> +/**
> + * do_ffa_msg_send_direct_req - implementation of the ping subcommand
> + * @cmdtp:		Command Table
> + * @flag:		flags
> + * @argc:		number of arguments
> + * @argv:		arguments
> + *
> + * This function sends data to the secure partition which the ID is provided
> + * as an argument. The function uses the arm_ffa driver helper function
> + * to send data.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +int  do_ffa_msg_send_direct_req(struct cmd_tbl *cmdtp, int flag, int argc,
> +				char *const argv[])
> +{
> +	struct ffa_interface_data func_data = {0};
> +	struct ffa_send_direct_data msg = {0};
> +	u32 pattern = 0xaabbccd0;
> +	u16 part_id;
> +	int ret;
> +
> +	if (argc != 1)
> +		return -EINVAL;
> +
> +	errno = 0;
> +	part_id = strtoul(argv[0], NULL, 16);
> +
> +	if (errno) {
> +		ffa_err("Invalid partition ID");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * telling the driver which partition to use
> +	 */
> +	func_data.data0_size = sizeof(part_id);
> +	func_data.data0 = &part_id;
> +
> +	/*
> +	 * filling the message data
> +	 */
> +	msg.a3 = ++pattern;
> +	msg.a4 = ++pattern;
> +	msg.a5 = ++pattern;
> +	msg.a6 = ++pattern;
> +	msg.a7 = ++pattern;
> +	func_data.data1_size = sizeof(msg);
> +	func_data.data1 = &msg;
> +
> +	ret = ffa_helper_msg_send_direct_req(&func_data);
> +	if (ret == FFA_ERR_STAT_SUCCESS) {
> +		u8 cnt;
> +
> +		ffa_info("SP response:\n[LSB]");
> +		for (cnt = 0;
> +		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u32);
> +		     cnt++)
> +			ffa_info("0x%x", ((u32 *)&msg)[cnt]);
> +	} else {
> +		ffa_err("Sending direct request error (%d)", ret);
> +	}
> +
> +	return ret;
> +}
> +
> +/**
> + *do_ffa_dev_list - implementation of the devlist subcommand
> + * @cmdtp: [in]		Command Table
> + * @flag:		flags
> + * @argc:		number of arguments
> + * @argv:		arguments
> + *
> + * This function queries the devices belonging to the UCLASS_FFA
> + * class. Currently, one device is expected to show up: the arm_ffa device
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +int do_ffa_dev_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +	struct udevice *dev = NULL;
> +	int i, ret;
> +
> +	ffa_info("arm_ffa uclass entries:");
> +
> +	for (i = 0, ret = uclass_first_device(UCLASS_FFA, &dev);
> +	     dev;
> +	     ret = uclass_next_device(&dev), i++) {
> +		if (ret)
> +			break;
> +
> +		ffa_info("entry %d - instance %08x, ops %08x, plat %08x",
> +			 i,
> +			 (u32)map_to_sysmem(dev),
> +			 (u32)map_to_sysmem(dev->driver->ops),
> +			 (u32)map_to_sysmem(dev_get_plat(dev)));
> +	}
> +
> +	return cmd_process_error(cmdtp, ret);
> +}
> +
> +static struct cmd_tbl armffa_commands[] = {
> +	U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_get_singular_partition_info, "", ""),
> +	U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_msg_send_direct_req, "", ""),
> +	U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_dev_list, "", ""),
> +};
> +
> +/**
> + * do_armffa - the armffa command main function
> + * @cmdtp:	Command Table
> + * @flag:		flags
> + * @argc:		number of arguments
> + * @argv:		arguments
> + *
> + * This function identifies which armffa subcommand to run.
> + * Then, it makes sure the arm_ffa device is probed and
> + * ready for use.
> + * Then, it runs the subcommand.
> + *
> + * Return:
> + *
> + * CMD_RET_SUCCESS: on success, otherwise failure
> + */
> +static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +	struct cmd_tbl *armffa_cmd;
> +	int ret;
> +
> +	if (argc < 2)
> +		return CMD_RET_USAGE;
> +
> +	armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands));
> +
> +	argc -= 2;
> +	argv += 2;
> +
> +	if (!armffa_cmd || argc > armffa_cmd->maxargs)
> +		return CMD_RET_USAGE;
> +
> +	ret = ffa_helper_init_device();
> +	if (ret != FFA_ERR_STAT_SUCCESS)
> +		return cmd_process_error(cmdtp, ret);
> +
> +	ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv);
> +
> +	return cmd_process_error(armffa_cmd, ret);
> +}
> +
> +U_BOOT_CMD(armffa, 4, 1, do_armffa,
> +	   "Arm FF-A operations test command",
> +	   "getpart <partition UUID>\n"
> +	   "	 - lists the partition(s) info\n"
> +	   "ping <partition ID>\n"
> +	   "	 - sends a data pattern to the specified partition\n"
> +	   "devlist\n"
> +	   "	 - displays the arm_ffa device info\n");
> diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
> index e503dfaebf..7b7cfe26b1 100644
> --- a/drivers/arm-ffa/Kconfig
> +++ b/drivers/arm-ffa/Kconfig
> @@ -4,6 +4,7 @@ config ARM_FFA_TRANSPORT
>   	bool "Enable Arm Firmware Framework for Armv8-A driver"
>   	depends on DM && ARM64
>   	select ARM_SMCCC if ARM64
> +	select CMD_ARMFFA
>   	select LIB_UUID
>   	select ARM_FFA_TRANSPORT_HELPERS
>   	help

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 2/6] arm_ffa: introduce armffa command
  2023-07-27  5:51   ` Heinrich Schuchardt
@ 2023-07-27  9:00     ` Abdellatif El Khlifi
  2023-07-28  1:52       ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27  9:00 UTC (permalink / raw)
  To: Heinrich Schuchardt; +Cc: nd, u-boot

Hi Heinrich,

On Thu, Jul 27, 2023 at 07:51:42AM +0200, Heinrich Schuchardt wrote:
> On 3/29/22 17:16, abdellatif.elkhlifi@arm.com wrote:
> > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > 
> > Provide armffa command showcasing the use of the FF-A driver
> > 
> > The armffa command allows to query secure partitions data from
> > the secure world and exchanging messages with the partitions.
> > 
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Cc: Tom Rini <trini@konsulko.com>
> > ---
> >   MAINTAINERS             |   1 +
> >   cmd/Kconfig             |  10 ++
> >   cmd/Makefile            |   2 +
> >   cmd/armffa.c            | 266 ++++++++++++++++++++++++++++++++++++++++
> >   drivers/arm-ffa/Kconfig |   1 +
> 
> We want to have all commands to be documented in /doc/usage/cmd/.
> 
> Could you, please, provide the missing /doc/usage/cmd/armffa.rst file.
> 

It's here [1].

[1]: https://lore.kernel.org/all/20230726094503.100497-6-abdellatif.elkhlifi@arm.com/#Z31doc:usage:cmd:armffa.rst

Cheers,
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-26 19:39                                                                                                                                                   ` Tom Rini
@ 2023-07-27  9:34                                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-27 13:30                                                                                                                                                       ` Tom Rini
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27  9:34 UTC (permalink / raw)
  To: Tom Rini
  Cc: gowtham.sureshkumar, ilias.apalodimas, jens.wiklander,
	meenakshi.aggarwal, nd, priyanka.jain, sjg, u-boot, wasim.khan

Hi Tom,

On Wed, Jul 26, 2023 at 03:39:12PM -0400, Tom Rini wrote:
> On Wed, Jul 26, 2023 at 10:45:02AM +0100, Abdellatif El Khlifi wrote:
> 
> > Add MM communication support using FF-A transport
> > 
> > This feature allows accessing MM partitions services through
> > EFI MM communication protocol. MM partitions such as StandAlonneMM
> > or smm-gateway secure partitions which reside in secure world.
> > 
> > An MM shared buffer and a door bell event are used to exchange
> > the data.
> > 
> > The data is used by EFI services such as GetVariable()/SetVariable()
> > and copied from the communication buffer to the MM shared buffer.
> > 
> > The secure partition is notified about availability of data in the
> > MM shared buffer by an FF-A message (door bell).
> > 
> > On such event, MM SP can read the data and updates the MM shared
> > buffer with the response data.
> > 
> > The response data is copied back to the communication buffer and
> > consumed by the EFI subsystem.
> > 
> > MM communication protocol supports FF-A 64-bit direct messaging.
> > 
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> > Cc: Tom Rini <trini@konsulko.com>
> > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > Cc: Jens Wiklander <jens.wiklander@linaro.org>
> 
> So, at this point in the series we impact lx2160ardb_tfa_stmm which is
> the only config in the tree prior to this series that sets
> CONFIG_EFI_MM_COMM_TEE. I'm not going to block this series[1] on
> updating lx2160ardb_tfa_stmm as well, but I do want to make sure the
> maintainers there are aware and can update the config to support the
> current state of this technology.
> 
> [1]: https://patchwork.ozlabs.org/project/uboot/list/?series=365876&state=*
> -- 

Following a decision made with Ilias, the new MM comms design works as follows:

- Try to communicate using FF-A bus first
- If that fails, try to communicate using Optee. So, platforms that don't support FF-A
  in the Secure side can still use Optee communication

This is done through the code below [1].

This logic needs CONFIG_ARM_FFA_TRANSPORT=y in the defconfig.

I added CONFIG_ARM_FFA_TRANSPORT=y to lx2160ardb_tfa_stmm_defconfig, CONFIG_EFI_MM_COMM_TEE is enabled and it builds fine.

Is it expected that lx2160ardb_tfa_stmm maintainers add CONFIG_ARM_FFA_TRANSPORT=y to lx2160ardb_tfa_stmm_defconfig ?

Cheers
Abdellatif

[1]: Selecting the MM comms method:

static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
...
	mm_comms = get_mm_comms();
	if (mm_comms == MM_COMMS_FFA)
		ret = ffa_mm_communicate(comm_buf, dsize);
	else
		ret = optee_mm_communicate(comm_buf, dsize);



^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v16 04/10] arm_ffa: introduce Arm FF-A support
  2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-07-27  9:56                                                                                                                                                   ` Ilias Apalodimas
  0 siblings, 0 replies; 478+ messages in thread
From: Ilias Apalodimas @ 2023-07-27  9:56 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: trini, nd, u-boot, Simon Glass, Jens Wiklander, Heinrich Schuchardt

On Wed, Jul 26, 2023 at 10:44:57AM +0100, Abdellatif El Khlifi wrote:
> Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0
> 
> The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
> describes interfaces (ABIs) that standardize communication
> between the Secure World and Normal World leveraging TrustZone
> technology.
> 
> This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
> on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
> querying the FF-A framework from the secure world.
> 
> The driver uses SMC32 calling convention which means using the first
> 32-bit data of the Xn registers.
> 
> All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
> which has 64-bit version supported.
> 
> Both 32-bit and 64-bit direct messaging are supported which allows both
> 32-bit and 64-bit clients to use the FF-A bus.
> 
> FF-A is a discoverable bus and similar to architecture features.
> FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> by the PSCI driver.
> 
> Clients are able to probe then use the FF-A bus by calling the DM class
> searching APIs (e.g: uclass_first_device).
> 
> The Secure World is considered as one entity to communicate with
> using the FF-A bus. FF-A communication is handled by one device and
> one instance (the bus). This FF-A driver takes care of all the
> interactions between Normal world and Secure World.
> 
> The driver exports its operations to be used by upper layers.
> 
> Exported operations:
> 
> - ffa_partition_info_get
> - ffa_sync_send_receive
> - ffa_rxtx_unmap
> 
> 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 please refer to the driver documentation [2].
> 
> [1]: https://developer.arm.com/documentation/den0077/latest/
> [2]: doc/arch/arm64.ffa.rst
> 
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Cc: Jens Wiklander <jens.wiklander@linaro.org>
> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
> 
> ---
> 
> Changelog:
> ===============
> 
> v13:
> 
> * doc minor change: specify in the readme that the user
>    should call ffa_rxtx_unmap() driver operation to unmap
>    the RX/TX buffers on demand.
> 
> v12:
> 
> * remove dscvry_info
> * replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
>    (user drivers can override it)
> * improve FFA_PARTITION_INFO_GET implementation
>    (clients no longer need to calloc a buffer)
> * address nits
> 
> v11:
> 
> * move ffa_try_discovery() from the uclass to the Arm FF-A driver
> * rename ffa_try_discovery() to arm_ffa_discover()
> * pass dev as an argument of arm_ffa_discover()
> * add arm_ prefix to the Arm FF-A driver functions
> * add emul field in struct ffa_discovery_info
> * address nits
> 
> v10:
> 
> * provide the driver operations through the Uclass
> * move the generic FF-A methods to the Uclass
> * keep Arm specific methods in the Arm driver (arm-ffa.c)
> * rename core.c to arm-ffa.c
> * address nits
> 
> v9:
> 
> * integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
> 
> v8:
> 
> * make ffa_get_partitions_info() second argument to be an SP count in both
>   modes
> * update ffa_bus_prvdata_get() to return a pointer rather than a pointer
>   address
> * remove packing from ffa_partition_info and ffa_send_direct_data structures
> * pass the FF-A bus device to the bus operations
> 
> v7:
> 
> * add support for 32-bit direct messaging
> * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
> * improve the declaration of error handling mapping
> * stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported
> 
> v6:
> 
> * drop use of EFI runtime support (We decided with Linaro to add this later)
> * drop discovery from initcalls (discovery will be on demand by FF-A users)
> * set the alignment of the RX/TX buffers to the larger translation granule size
> * move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
> * update the documentation and move it to doc/arch/arm64.ffa.rst
> 
> v4:
> 
> * add doc/README.ffa.drv
> * moving the FF-A driver work to drivers/firmware/arm-ffa
> * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
>   #if defined by #if CONFIG_IS_ENABLED
> * improving error handling by mapping the FF-A errors to standard errors
>   and logs
> * replacing panics with an error log and returning an error code
> * improving features discovery in FFA_FEATURES by introducing
>   rxtx_min_pages private data field
> * add ffa_remove and ffa_unbind functions
> * improve how the driver behaves when bus discovery is done more than
>   once
> 
> v3:
> 
> * align the interfaces of the U-Boot FF-A driver with those in the linux
>   FF-A driver
> * remove the FF-A helper layer
> * make the U-Boot FF-A driver independent from EFI
> * provide an optional config that enables copying the driver data to EFI
>   runtime section at ExitBootServices service
> * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
> 
> v2:
> 
> * make FF-A bus discoverable using device_{bind, probe} APIs
> * remove device tree support
> 
> v1:
> 
> * introduce FF-A bus driver with device tree support
> 
> MAINTAINERS                                   |    8 +
>  doc/arch/arm64.ffa.rst                        |  238 ++++
>  doc/arch/index.rst                            |    1 +
>  drivers/Makefile                              |    1 +
>  drivers/firmware/Kconfig                      |    1 +
>  drivers/firmware/arm-ffa/Kconfig              |   36 +
>  drivers/firmware/arm-ffa/Makefile             |    8 +
>  drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
>  drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
>  .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |   14 +
>  include/arm_ffa.h                             |  213 ++++
>  include/arm_ffa_priv.h                        |  246 ++++
>  include/dm/uclass-id.h                        |    6 +
>  13 files changed, 1941 insertions(+)
>  create mode 100644 doc/arch/arm64.ffa.rst
>  create mode 100644 drivers/firmware/arm-ffa/Kconfig
>  create mode 100644 drivers/firmware/arm-ffa/Makefile
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
>  create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
>  create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
>  create mode 100644 include/arm_ffa.h
>  create mode 100644 include/arm_ffa_priv.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 4324965d26..4fd5768de0 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -266,6 +266,14 @@ F:	drivers/net/cortina_ni.h
>  F:	drivers/net/phy/ca_phy.c
>  F:	configs/cortina_presidio-asic-pnand_defconfig
>  
> +ARM FF-A
> +M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +S:	Maintained
> +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>
>  M:	Fabio Estevam <festevam@gmail.com>
> diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
> new file mode 100644
> index 0000000000..4f817f053c
> --- /dev/null
> +++ b/doc/arch/arm64.ffa.rst
> @@ -0,0 +1,238 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +
> +Arm FF-A Support
> +================
> +
> +Summary
> +-------
> +
> +FF-A stands for Firmware Framework for Arm A-profile processors.
> +
> +FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> +communicate with each other. A partition could be a VM in the Normal or Secure world, an
> +application in S-EL0, or a Trusted OS in S-EL1.
> +
> +The U-Boot FF-A support (the bus) implements the interfaces to communicate
> +with partitions in the Secure world aka Secure partitions (SPs).
> +
> +The FF-A support specifically focuses on communicating with SPs that
> +isolate portions of EFI runtime services that must run in a protected
> +environment which is inaccessible by the Host OS or Hypervisor.
> +Examples of such services are set/get variables.
> +
> +The FF-A support uses the SMC ABIs defined by the FF-A specification to:
> +
> +- Discover the presence of SPs of interest
> +- Access an SP's service through communication protocols
> +  e.g. EFI MM communication protocol
> +
> +At this stage of development only EFI boot-time services are supported.
> +Runtime support will be added in future developments.
> +
> +The U-Boot FF-A support provides the following parts:
> +
> +- A Uclass driver providing generic FF-A methods.
> +- An Arm FF-A device driver providing Arm-specific methods and reusing the Uclass methods.
> +
> +FF-A and SMC specifications
> +-------------------------------------------
> +
> +The current implementation of the U-Boot FF-A support relies on
> +`FF-A v1.0 specification`_ and uses SMC32 calling convention which
> +means using the first 32-bit data of the Xn registers.
> +
> +At this stage we only need the FF-A v1.0 features.
> +
> +The FF-A support has been tested with OP-TEE which supports SMC32 calling
> +convention.
> +
> +Hypervisors are supported if they are configured to trap SMC calls.
> +
> +The FF-A support uses 64-bit registers as per `SMC Calling Convention v1.2 specification`_.
> +
> +Supported hardware
> +--------------------------------
> +
> +Aarch64 plaforms
> +
> +Configuration
> +----------------------
> +
> +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.
> +
> +FF-A ABIs under the hood
> +---------------------------------------
> +
> +Invoking an FF-A ABI involves providing to the secure world/hypervisor the
> +expected arguments from the ABI.
> +
> +On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers.
> +Then, an SMC instruction is executed.
> +
> +At the secure side level or hypervisor the ABI is handled at a higher exception
> +level and the arguments are read and processed.
> +
> +The response is put back through x0 to x7 registers and control is given back
> +to the U-Boot Arm FF-A driver (non-secure world).
> +
> +The driver reads the response and processes it accordingly.
> +
> +This methodology applies to all the FF-A ABIs.
> +
> +FF-A bus discovery on Arm 64-bit platforms
> +---------------------------------------------
> +
> +When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
> +an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
> +This discovery mechanism is performed by the PSCI driver.
> +
> +The PSCI driver comes with a PSCI device tree node which is the root node for all
> +architecture features including FF-A bus.
> +
> +::
> +
> +   => dm tree
> +
> +    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.
> +
> +In case of FF-A, the callback is arm_ffa_is_supported() which tries to discover the
> +FF-A framework by querying the FF-A framework version from secure world using
> +FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
> +mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver
> +with the device using device_bind_driver().
> +
> +At this stage the FF-A bus is registered with the DM and can be interacted with using
> +the DM APIs.
> +
> +Clients are able to probe then use the FF-A bus by calling uclass_first_device().
> +Please refer to the armffa command implementation as an example of how to probe
> +and interact with the FF-A bus.
> +
> +When calling uclass_first_device(), the FF-A driver is probed and ends up calling
> +ffa_do_probe() provided by the Uclass which does the following:
> +
> +    - saving the FF-A framework version in uc_priv
> +    - querying from secure world the u-boot endpoint ID
> +    - querying from secure world the supported features of FFA_RXTX_MAP
> +    - mapping the RX/TX buffers
> +    - querying from secure world all the partitions information
> +
> +When one of the above actions fails, probing fails and the driver stays not active
> +and can be probed again if needed.
> +
> +Requirements for clients
> +-------------------------------------
> +
> +When using the FF-A bus with EFI, clients must query the SPs they are looking for
> +during EFI boot-time mode using the service UUID.
> +
> +The RX/TX buffers are only available at EFI boot-time. Querying partitions is
> +done at boot time and data is cached for future use.
> +
> +RX/TX buffers should be unmapped before EFI runtime mode starts.
> +The driver provides a bus operation for that called ffa_rxtx_unmap().
> +
> +The user should call ffa_rxtx_unmap() to unmap the RX/TX buffers when required
> +(e.g: at efi_exit_boot_services()).
> +
> +The Linux kernel allocates its own RX/TX buffers. To be able to register these kernel buffers
> +with secure world, the U-Boot's RX/TX buffers should be unmapped before EFI runtime starts.
> +
> +When invoking FF-A direct messaging, clients should specify which ABI protocol
> +they want to use (32-bit vs 64-bit). Selecting the protocol means using
> +the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
> +The calling convention between U-Boot and the secure world stays the same: SMC32.
> +
> +Requirements for user drivers
> +-------------------------------------
> +
> +Users who want to implement their custom FF-A device driver while reusing the FF-A Uclass can do so
> +by implementing their own invoke_ffa_fn() in the user driver.
> +
> +The bus driver layer
> +------------------------------
> +
> +FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c
> +
> +The following features are provided:
> +
> +- Support for the 32-bit version of the following ABIs:
> +
> +    - FFA_VERSION
> +    - FFA_ID_GET
> +    - FFA_FEATURES
> +    - FFA_PARTITION_INFO_GET
> +    - FFA_RXTX_UNMAP
> +    - FFA_RX_RELEASE
> +    - FFA_RUN
> +    - FFA_ERROR
> +    - FFA_SUCCESS
> +    - FFA_INTERRUPT
> +    - FFA_MSG_SEND_DIRECT_REQ
> +    - FFA_MSG_SEND_DIRECT_RESP
> +
> +- Support for the 64-bit version of the following ABIs:
> +
> +    - FFA_RXTX_MAP
> +    - FFA_MSG_SEND_DIRECT_REQ
> +    - FFA_MSG_SEND_DIRECT_RESP
> +
> +- Processing the received data from the secure world/hypervisor and caching it
> +
> +- Hiding from upper layers the FF-A protocol and registers details. Upper
> +  layers focus on exchanged data, FF-A support takes care of how to transport
> +  that to the secure world/hypervisor using FF-A
> +
> +- FF-A support provides driver operations to be used by upper layers:
> +
> +    - ffa_partition_info_get
> +    - ffa_sync_send_receive
> +    - ffa_rxtx_unmap
> +
> +- FF-A bus discovery makes sure FF-A framework is responsive and compatible
> +  with the driver
> +
> +- FF-A bus can be compiled and used without EFI
> +
> +Example of boot logs with FF-A enabled
> +--------------------------------------
> +
> +For example, when using FF-A with Corstone-1000 the logs are as follows:
> +
> +::
> +
> +   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64
> +
> +   DRAM:  2 GiB
> +   Arm FF-A framework discovery
> +   FF-A driver 1.0
> +   FF-A framework 1.0
> +   FF-A versions are compatible
> +   ...
> +   FF-A driver 1.0
> +   FF-A framework 1.0
> +   FF-A versions are compatible
> +   EFI: MM partition ID 0x8003
> +   ...
> +   EFI stub: Booting Linux Kernel...
> +   ...
> +   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
> +   Machine model: ARM Corstone1000 FPGA MPS3 board
> +
> +Contributors
> +------------
> +   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> +
> +.. _`FF-A v1.0 specification`: https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e
> +.. _`SMC Calling Convention v1.2 specification`: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6
> diff --git a/doc/arch/index.rst b/doc/arch/index.rst
> index b8da4b8c8e..2f916f4026 100644
> --- a/doc/arch/index.rst
> +++ b/doc/arch/index.rst
> @@ -8,6 +8,7 @@ Architecture-specific doc
>  
>     arc
>     arm64
> +   arm64.ffa
>     m68k
>     mips
>     nios2
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 78dcf62f76..5044f45253 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -115,6 +115,7 @@ obj-y += iommu/
>  obj-y += smem/
>  obj-y += thermal/
>  obj-$(CONFIG_TEE) += tee/
> +obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
>  obj-y += axi/
>  obj-y += ufs/
>  obj-$(CONFIG_W1) += w1/
> diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
> index eae1c8ddc9..8789b1ea14 100644
> --- a/drivers/firmware/Kconfig
> +++ b/drivers/firmware/Kconfig
> @@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
>  	  the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
>  	  services if any and reported as supported by the SMCCC firmware.
>  
> +source "drivers/firmware/arm-ffa/Kconfig"
>  source "drivers/firmware/scmi/Kconfig"
> diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
> new file mode 100644
> index 0000000000..9200c8028b
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/Kconfig
> @@ -0,0 +1,36 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +config ARM_FFA_TRANSPORT
> +	bool "Enable Arm Firmware Framework for Armv8-A driver"
> +	depends on DM && ARM64
> +	select ARM_SMCCC
> +	select ARM_SMCCC_FEATURES
> +	select LIB_UUID
> +	select DEVRES
> +	help
> +	  The Firmware Framework for Arm A-profile processors (FF-A)
> +	  describes interfaces (ABIs) that standardize communication
> +	  between the Secure World and Normal World leveraging TrustZone
> +	  technology.
> +
> +	  The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32
> +	  calling convention.
> +
> +	  FF-A specification:
> +
> +	  https://developer.arm.com/documentation/den0077/a/?lang=en
> +
> +	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
> +	  FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> +	  by the PSCI driver.
> +	  The Secure World is considered as one entity to communicate with
> +	  using the FF-A bus.
> +	  FF-A communication is handled by one device and one instance (the bus).
> +	  The FF-A support on U-Boot  takes care of all the interactions between Normal
> +	  world and Secure World.
> +
> +	  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
> +
> diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
> new file mode 100644
> index 0000000000..11b1766285
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/Makefile
> @@ -0,0 +1,8 @@
> +# 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>
> +
> +obj-y += arm-ffa-uclass.o arm-ffa.o
> diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> new file mode 100644
> index 0000000000..ffa9d81fa7
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
> @@ -0,0 +1,1065 @@
> +// 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 <arm_ffa_priv.h>
> +#include <dm.h>
> +#include <log.h>
> +#include <malloc.h>
> +#include <string.h>
> +#include <uuid.h>
> +#include <asm/global_data.h>
> +#include <dm/device-internal.h>
> +#include <dm/devres.h>
> +#include <dm/root.h>
> +#include <linux/errno.h>
> +#include <linux/sizes.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* Error mapping declarations */
> +
> +int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
> +	[NOT_SUPPORTED] = -EOPNOTSUPP,
> +	[INVALID_PARAMETERS] = -EINVAL,
> +	[NO_MEMORY] = -ENOMEM,
> +	[BUSY] = -EBUSY,
> +	[INTERRUPTED] = -EINTR,
> +	[DENIED] = -EACCES,
> +	[RETRY] = -EAGAIN,
> +	[ABORTED] = -ECANCELED,
> +};
> +
> +static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
> +	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
> +		{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
> +		{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
> +		{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
> +		{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> +			[INVALID_PARAMETERS] =
> +			"INVALID_PARAMETERS: Unrecognized UUID",
> +			[NO_MEMORY] =
> +			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
> +			[BUSY] =
> +			"BUSY: RX buffer of the caller is not free",
> +			[DENIED] =
> +			"DENIED: Callee is not in a state to handle this request",
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
> +		{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
> +			[INVALID_PARAMETERS] =
> +			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
> +		{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
> +			[DENIED] =
> +			"DENIED: Caller did not have ownership of the RX buffer",
> +		},
> +	},
> +	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
> +		{
> +			[NOT_SUPPORTED] =
> +			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
> +			[INVALID_PARAMETERS] =
> +			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
> +			[NO_MEMORY] =
> +			"NO_MEMORY: Not enough memory",
> +			[DENIED] =
> +			"DENIED: Buffer pair already registered",
> +		},
> +	},
> +};
> +
> +/**
> + * ffa_to_std_errno() - convert FF-A error code to standard error code
> + * @ffa_errno:	Error code returned by the FF-A ABI
> + *
> + * Map the given FF-A error code as specified
> + * by the spec to a u-boot standard error code.
> + *
> + * Return:
> + *
> + * The standard error code on success. . Otherwise, failure
> + */
> +static int ffa_to_std_errno(int ffa_errno)
> +{
> +	int err_idx = -ffa_errno;
> +
> +	/* Map the FF-A error code to the standard u-boot error code */
> +	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
> +		return ffa_to_std_errmap[err_idx];
> +	return -EINVAL;
> +}
> +
> +/**
> + * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI
> + * @ffa_id:	FF-A ABI ID
> + * @ffa_errno:	Error code returned by the FF-A ABI
> + *
> + * Map the FF-A error code to the error log relevant to the
> + * selected FF-A ABI. Then the error log is printed.
> + *
> + * Return:
> + *
> + * 0 on success. . Otherwise, failure
> + */
> +static int ffa_print_error_log(u32 ffa_id, int ffa_errno)
> +{
> +	int err_idx = -ffa_errno, abi_idx = 0;
> +
> +	/* Map the FF-A error code to the corresponding error log */
> +
> +	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
> +		return -EINVAL;
> +
> +	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
> +		return -EINVAL;
> +
> +	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
> +	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
> +		return -EINVAL;
> +
> +	if (!err_msg_map[abi_idx].err_str[err_idx])
> +		return -EINVAL;
> +
> +	log_err("%s\n", err_msg_map[abi_idx].err_str[err_idx]);
> +
> +	return 0;
> +}
> +
> +/* FF-A ABIs implementation (U-Boot side) */
> +
> +/**
> + * 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 low level SMC implementation.
> + * This function should be implemented by the user driver.
> + */
> +void __weak invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
> +{
> +}
> +
> +/**
> + * ffa_get_version_hdlr() - FFA_VERSION handler function
> + * @dev: The FF-A bus device
> + *
> + * Implement FFA_VERSION FF-A function
> + * to get from the secure world the FF-A framework version
> + * FFA_VERSION is used to discover the FF-A framework.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_get_version_hdlr(struct udevice *dev)
> +{
> +	u16 major, minor;
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +	struct ffa_priv *uc_priv;
> +
> +	invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
> +			}, &res);
> +
> +	ffa_errno = res.a0;
> +	if (ffa_errno < 0) {
> +		ffa_print_error_log(FFA_VERSION, ffa_errno);
> +		return ffa_to_std_errno(ffa_errno);
> +	}
> +
> +	major = GET_FFA_MAJOR_VERSION(res.a0);
> +	minor = GET_FFA_MINOR_VERSION(res.a0);
> +
> +	log_info("FF-A driver %d.%d\nFF-A framework %d.%d\n",
> +		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> +
> +	if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) {
> +		log_info("FF-A versions are compatible\n");
> +
> +		if (dev) {
> +			uc_priv = dev_get_uclass_priv(dev);
> +			if (uc_priv)
> +				uc_priv->fwk_version = res.a0;
> +		}
> +
> +		return 0;
> +	}
> +
> +	log_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
> +		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
> +
> +	return -EPROTONOSUPPORT;
> +}
> +
> +/**
> + * ffa_get_endpoint_id() - FFA_ID_GET handler function
> + * @dev: The FF-A bus device
> + *
> + * Implement FFA_ID_GET FF-A function
> + * to get from the secure world u-boot endpoint ID
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_get_endpoint_id(struct udevice *dev)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
> +
> +	invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_ID_GET),
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		uc_priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
> +		log_debug("FF-A endpoint ID is %u\n", uc_priv->id);
> +
> +		return 0;
> +	}
> +
> +	ffa_errno = res.a2;
> +
> +	ffa_print_error_log(FFA_ID_GET, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_set_rxtx_buffers_pages_cnt() - set the minimum number of pages in each of the RX/TX buffers
> + * @dev: The FF-A bus device
> + * @prop_field: properties field obtained from FFA_FEATURES ABI
> + *
> + * Set the minimum number of pages in each of the RX/TX buffers in uc_priv
> + *
> + * Return:
> + *
> + * rxtx_min_pages field contains the returned number of pages
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field)
> +{
> +	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
> +
> +	switch (prop_field) {
> +	case RXTX_4K:
> +		uc_priv->pair.rxtx_min_pages = 1;
> +		break;
> +	case RXTX_16K:
> +		uc_priv->pair.rxtx_min_pages = 4;
> +		break;
> +	case RXTX_64K:
> +		uc_priv->pair.rxtx_min_pages = 16;
> +		break;
> +	default:
> +		log_err("RX/TX buffer size not supported\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_get_rxtx_map_features_hdlr() - FFA_FEATURES handler function with FFA_RXTX_MAP argument
> + * @dev: The FF-A bus device
> + *
> + * Implement FFA_FEATURES FF-A function to retrieve the FFA_RXTX_MAP features
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_get_rxtx_map_features_hdlr(struct udevice *dev)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_FEATURES),
> +			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> +		return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2);
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_FEATURES, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_free_rxtx_buffers() - free the RX/TX buffers
> + * @dev: The FF-A bus device
> + *
> + * Free the RX/TX buffers
> + */
> +static void ffa_free_rxtx_buffers(struct udevice *dev)
> +{
> +	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
> +
> +	log_debug("Freeing FF-A RX/TX buffers\n");
> +
> +	if (uc_priv->pair.rxbuf) {
> +		free(uc_priv->pair.rxbuf);
> +		uc_priv->pair.rxbuf = NULL;
> +	}
> +
> +	if (uc_priv->pair.txbuf) {
> +		free(uc_priv->pair.txbuf);
> +		uc_priv->pair.txbuf = NULL;
> +	}
> +}
> +
> +/**
> + * ffa_alloc_rxtx_buffers() - allocate the RX/TX buffers
> + * @dev: The FF-A bus device
> + *
> + * Used by ffa_map_rxtx_buffers to allocate
> + * the RX/TX buffers before mapping them. The allocated memory is physically
> + * contiguous since memalign ends up calling malloc which allocates
> + * contiguous memory in u-boot.
> + * The size of the memory allocated is the minimum allowed.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_alloc_rxtx_buffers(struct udevice *dev)
> +{
> +	u64 bytes;
> +	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
> +
> +	log_debug("Using %lu 4KB page(s) for FF-A RX/TX buffers size\n",
> +		  uc_priv->pair.rxtx_min_pages);
> +
> +	bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
> +
> +	/*
> +	 * The alignment of the RX and TX buffers must be equal
> +	 * to the larger translation granule size
> +	 * Assumption: Memory allocated with memalign is always physically contiguous
> +	 */
> +
> +	uc_priv->pair.rxbuf = memalign(bytes, bytes);
> +	if (!uc_priv->pair.rxbuf) {
> +		log_err("failure to allocate RX buffer\n");
> +		return -ENOBUFS;
> +	}
> +
> +	log_debug("FF-A RX buffer at virtual address %p\n", uc_priv->pair.rxbuf);
> +
> +	uc_priv->pair.txbuf = memalign(bytes, bytes);
> +	if (!uc_priv->pair.txbuf) {
> +		free(uc_priv->pair.rxbuf);
> +		uc_priv->pair.rxbuf = NULL;
> +		log_err("failure to allocate the TX buffer\n");
> +		return -ENOBUFS;
> +	}
> +
> +	log_debug("FF-A TX buffer at virtual address %p\n", uc_priv->pair.txbuf);
> +
> +	/* Make sure the buffers are cleared before use */
> +	memset(uc_priv->pair.rxbuf, 0, bytes);
> +	memset(uc_priv->pair.txbuf, 0, bytes);
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_map_rxtx_buffers_hdlr() - FFA_RXTX_MAP handler function
> + * @dev: The FF-A bus device
> + *
> + * Implement FFA_RXTX_MAP FF-A function to map the RX/TX buffers
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_map_rxtx_buffers_hdlr(struct udevice *dev)
> +{
> +	int ret;
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
> +
> +	ret = ffa_alloc_rxtx_buffers(dev);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * we need to pass the physical addresses of the RX/TX buffers
> +	 * in u-boot physical/virtual mapping is 1:1
> +	 * no need to convert from virtual to physical
> +	 */
> +
> +	invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
> +			.a1 = map_to_sysmem(uc_priv->pair.txbuf),
> +			.a2 = map_to_sysmem(uc_priv->pair.rxbuf),
> +			.a3 = uc_priv->pair.rxtx_min_pages,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		log_debug("FF-A RX/TX buffers mapped\n");
> +		return 0;
> +	}
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
> +
> +	ffa_free_rxtx_buffers(dev);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
> + * @dev: The FF-A bus device
> + *
> + * Implement FFA_RXTX_UNMAP FF-A function to unmap the RX/TX buffers
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +	struct ffa_priv *uc_priv;
> +
> +	log_debug("unmapping FF-A RX/TX buffers\n");
> +
> +	uc_priv = dev_get_uclass_priv(dev);
> +
> +	invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
> +			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id),
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		ffa_free_rxtx_buffers(dev);
> +		return 0;
> +	}
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_release_rx_buffer_hdlr() - FFA_RX_RELEASE handler function
> + * @dev: The FF-A bus device
> + *
> + * Invoke FFA_RX_RELEASE FF-A function to release the ownership of the RX buffer
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_release_rx_buffer_hdlr(struct udevice *dev)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
> +		return 0;
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_uuid_are_identical() - check whether two given UUIDs are identical
> + * @uuid1: first UUID
> + * @uuid2: second UUID
> + *
> + * Used by ffa_read_partitions_info to search for a UUID in the partitions descriptors table
> + *
> + * Return:
> + *
> + * 1 when UUIDs match. Otherwise, 0
> + */
> +static bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
> +				   const struct ffa_partition_uuid *uuid2)
> +{
> +	if (!uuid1 || !uuid2)
> +		return 0;
> +
> +	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
> +}
> +
> +/**
> + * ffa_read_partitions_info() - read queried partition data
> + * @dev: The FF-A bus device
> + * @count: The number of partitions queried
> + * @part_uuid: Pointer to the partition(s) UUID
> + *
> + * Read the partitions information returned by the FFA_PARTITION_INFO_GET and saves it in uc_priv
> + *
> + * Return:
> + *
> + * uc_priv is updated with the partition(s) information
> + * 0 is returned on success. Otherwise, failure
> + */
> +static int ffa_read_partitions_info(struct udevice *dev, u32 count,
> +				    struct ffa_partition_uuid *part_uuid)
> +{
> +	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
> +
> +	if (!count) {
> +		log_err("no partition detected\n");
> +		return -ENODATA;
> +	}
> +
> +	log_debug("Reading FF-A partitions data from the RX buffer\n");
> +
> +	if (!part_uuid) {
> +		/* Querying information of all partitions */
> +		u64 buf_bytes;
> +		u64 data_bytes;
> +		u32 desc_idx;
> +		struct ffa_partition_info *parts_info;
> +
> +		data_bytes = count * sizeof(struct ffa_partition_desc);
> +
> +		buf_bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
> +
> +		if (data_bytes > buf_bytes) {
> +			log_err("partitions data size exceeds the RX buffer size:\n");
> +			log_err("    sizes in bytes: data %llu , RX buffer %llu\n",
> +				data_bytes,
> +				buf_bytes);
> +
> +			return -ENOMEM;
> +		}
> +
> +		uc_priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO);
> +		if (!uc_priv->partitions.descs) {
> +			log_err("cannot  allocate partitions data buffer\n");
> +			return -ENOMEM;
> +		}
> +
> +		parts_info = uc_priv->pair.rxbuf;
> +
> +		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
> +			uc_priv->partitions.descs[desc_idx].info =
> +				parts_info[desc_idx];
> +
> +			log_debug("FF-A partition ID %x : info cached\n",
> +				  uc_priv->partitions.descs[desc_idx].info.id);
> +		}
> +
> +		uc_priv->partitions.count = count;
> +
> +		log_debug("%d FF-A partition(s) found and cached\n", count);
> +
> +	} else {
> +		u32 rx_desc_idx, cached_desc_idx;
> +		struct ffa_partition_info *parts_info;
> +		u8 desc_found;
> +
> +		parts_info = uc_priv->pair.rxbuf;
> +
> +		/*
> +		 * Search for the SP IDs read from the RX buffer
> +		 * in the already cached SPs.
> +		 * Update the UUID when ID found.
> +		 */
> +		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
> +			desc_found = 0;
> +
> +			/* Search the current ID in the cached partitions */
> +			for (cached_desc_idx = 0;
> +			     cached_desc_idx < uc_priv->partitions.count;
> +			     cached_desc_idx++) {
> +				/* Save the UUID */
> +				if (uc_priv->partitions.descs[cached_desc_idx].info.id ==
> +				    parts_info[rx_desc_idx].id) {
> +					uc_priv->partitions.descs[cached_desc_idx].sp_uuid =
> +						*part_uuid;
> +
> +					desc_found = 1;
> +					break;
> +				}
> +			}
> +
> +			if (!desc_found)
> +				return -ENODATA;
> +		}
> +	}
> +
> +	return  0;
> +}
> +
> +/**
> + * ffa_query_partitions_info() - invoke FFA_PARTITION_INFO_GET and save partitions data
> + * @dev: The FF-A bus device
> + * @part_uuid: Pointer to the partition(s) UUID
> + * @pcount: Pointer to the number of partitions variable filled when querying
> + *
> + * Execute the FFA_PARTITION_INFO_GET to query the partitions data.
> + * Then, call ffa_read_partitions_info to save the data in uc_priv.
> + *
> + * After reading the data the RX buffer is released using ffa_release_rx_buffer
> + *
> + * Return:
> + *
> + * When part_uuid is NULL, all partitions data are retrieved from secure world
> + * When part_uuid is non NULL, data for partitions matching the given UUID are
> + * retrieved and the number of partitions is returned
> + * 0 is returned on success. Otherwise, failure
> + */
> +static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid,
> +				     u32 *pcount)
> +{
> +	struct ffa_partition_uuid query_uuid = {0};
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +
> +	/*
> +	 * If a UUID is specified. Information for one or more
> +	 * partitions in the system is queried. Otherwise, information
> +	 * for all installed partitions is queried
> +	 */
> +
> +	if (part_uuid) {
> +		if (!pcount)
> +			return -EINVAL;
> +
> +		query_uuid = *part_uuid;
> +	} else if (pcount) {
> +		return -EINVAL;
> +	}
> +
> +	invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
> +			.a1 = query_uuid.a1,
> +			.a2 = query_uuid.a2,
> +			.a3 = query_uuid.a3,
> +			.a4 = query_uuid.a4,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		int ret;
> +
> +		/*
> +		 * res.a2 contains the count of partition information descriptors
> +		 * populated in the RX buffer
> +		 */
> +		if (res.a2) {
> +			ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid);
> +			if (ret) {
> +				log_err("failed reading SP(s) data , err (%d)\n", ret);
> +				ffa_release_rx_buffer_hdlr(dev);
> +				return -EINVAL;
> +			}
> +		}
> +
> +		/* Return the SP count (when querying using a UUID) */
> +		if (pcount)
> +			*pcount = (u32)res.a2;
> +
> +		/*
> +		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
> +		 * is assigned to the consumer (u-boot). So, we need to give
> +		 * the ownership back to the SPM or hypervisor
> +		 */
> +		ret = ffa_release_rx_buffer_hdlr(dev);
> +
> +		return ret;
> +	}
> +
> +	ffa_errno = res.a2;
> +	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
> +
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/**
> + * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
> + *	@uuid_str: pointer to the UUID string
> + *	@sp_count: address of the variable containing the number of partitions matching the UUID
> + *			 The variable is set by the driver
> + *	@sp_descs: address of the descriptors of the partitions matching the UUID
> + *			 The address is set by the driver
> + *
> + * Return the number of partitions and their descriptors matching the UUID
> + *
> + * Query the secure partition data from uc_priv.
> + * If not found, invoke FFA_PARTITION_INFO_GET FF-A function to query the partition information
> + * from secure world.
> + *
> + * A client of the FF-A driver should know the UUID of the service it wants to
> + * access. It should use the UUID to request the FF-A driver to provide the
> + * partition(s) information of the service. The FF-A driver uses
> + * PARTITION_INFO_GET to obtain this information. This is implemented through
> + * ffa_get_partitions_info_hdlr() function.
> + * If the partition(s) matching the UUID found, the partition(s) information and the
> + * number are returned.
> + * If no partition matching the UUID is found in the cached area, a new FFA_PARTITION_INFO_GET
> + * call is issued.
> + * If not done yet, the UUID is updated in the cached area.
> + * This assumes that partitions data does not change in the secure world.
> + * Otherwise u-boot will have an outdated partition data. The benefit of caching
> + * the information in the FF-A driver is to accommodate discovery after
> + * ExitBootServices().
> + *
> + * Return:
> + *
> + * @sp_count: the number of partitions
> + * @sp_descs: address of the partitions descriptors
> + *
> + * On success 0 is returned. Otherwise, failure
> + */
> +int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
> +				 u32 *sp_count, struct ffa_partition_desc **sp_descs)
> +{
> +	u32 i;
> +	struct ffa_partition_uuid part_uuid = {0};
> +	struct ffa_priv *uc_priv;
> +	struct ffa_partition_desc *rx_descs;
> +
> +	uc_priv = dev_get_uclass_priv(dev);
> +
> +	if (!uc_priv->partitions.count || !uc_priv->partitions.descs) {
> +		log_err("no partition installed\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!uuid_str) {
> +		log_err("no UUID provided\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!sp_count) {
> +		log_err("no count argument provided\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!sp_descs) {
> +		log_err("no info argument provided\n");
> +		return -EINVAL;
> +	}
> +
> +	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
> +		log_err("invalid UUID\n");
> +		return -EINVAL;
> +	}
> +
> +	log_debug("Searching FF-A partitions using the provided UUID\n");
> +
> +	*sp_count = 0;
> +	*sp_descs = uc_priv->pair.rxbuf;
> +	rx_descs = *sp_descs;
> +
> +	/* Search in the cached partitions */
> +	for (i = 0; i < uc_priv->partitions.count; i++)
> +		if (ffa_uuid_are_identical(&uc_priv->partitions.descs[i].sp_uuid,
> +					   &part_uuid)) {
> +			log_debug("FF-A partition ID %x matches the provided UUID\n",
> +				  uc_priv->partitions.descs[i].info.id);
> +
> +			(*sp_count)++;
> +			*rx_descs++ = uc_priv->partitions.descs[i];
> +			}
> +
> +	if (!(*sp_count)) {
> +		int ret;
> +
> +		log_debug("No FF-A partition found. Querying framework ...\n");
> +
> +		ret = ffa_query_partitions_info(dev, &part_uuid, sp_count);
> +
> +		if (!ret) {
> +			log_debug("Number of FF-A partition(s) matching the UUID: %d\n", *sp_count);
> +
> +			if (*sp_count)
> +				ret = ffa_get_partitions_info_hdlr(dev, uuid_str, sp_count,
> +								   sp_descs);
> +			else
> +				ret = -ENODATA;
> +		}
> +
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_cache_partitions_info() - Query and saves all secure partitions data
> + * @dev: The FF-A bus device
> + *
> + * Invoke FFA_PARTITION_INFO_GET FF-A function to query from secure world
> + * all partitions information.
> + *
> + * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
> + * All installed partitions information are returned. We cache them in uc_priv
> + * and we keep the UUID field empty (in FF-A 1.0 UUID is not provided by the partition descriptor)
> + *
> + * Called at the device probing level.
> + * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_cache_partitions_info(struct udevice *dev)
> +{
> +	return ffa_query_partitions_info(dev, NULL, NULL);
> +}
> +
> +/**
> + * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> + * @dev: The FF-A bus device
> + * @dst_part_id: destination partition ID
> + * @msg: pointer to the message data preallocated by the client (in/out)
> + * @is_smc64: select 64-bit or 32-bit FF-A ABI
> + *
> + * Implement FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * FF-A functions.
> + *
> + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> + * The response from the secure partition is handled by reading the
> + * FFA_MSG_SEND_DIRECT_RESP arguments.
> + *
> + * The maximum size of the data that can be exchanged is 40 bytes which is
> + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
> +				 struct ffa_send_direct_data *msg, bool is_smc64)
> +{
> +	ffa_value_t res = {0};
> +	int ffa_errno;
> +	u64 req_mode, resp_mode;
> +	struct ffa_priv *uc_priv;
> +
> +	uc_priv = dev_get_uclass_priv(dev);
> +
> +	/* No partition installed */
> +	if (!uc_priv->partitions.count || !uc_priv->partitions.descs)
> +		return -ENODEV;
> +
> +	if (is_smc64) {
> +		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
> +		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
> +	} else {
> +		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
> +		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
> +	}
> +
> +	invoke_ffa_fn((ffa_value_t){
> +			.a0 = req_mode,
> +			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id) |
> +				PREP_PART_ENDPOINT_ID(dst_part_id),
> +			.a2 = 0,
> +			.a3 = msg->data0,
> +			.a4 = msg->data1,
> +			.a5 = msg->data2,
> +			.a6 = msg->data3,
> +			.a7 = msg->data4,
> +			}, &res);
> +
> +	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
> +		invoke_ffa_fn((ffa_value_t){
> +			.a0 = FFA_SMC_32(FFA_RUN),
> +			.a1 = res.a1,
> +			}, &res);
> +
> +	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
> +		/* Message sent with no response */
> +		return 0;
> +	}
> +
> +	if (res.a0 == resp_mode) {
> +		/* Message sent with response extract the return data */
> +		msg->data0 = res.a3;
> +		msg->data1 = res.a4;
> +		msg->data2 = res.a5;
> +		msg->data3 = res.a6;
> +		msg->data4 = res.a7;
> +
> +		return 0;
> +	}
> +
> +	ffa_errno = res.a2;
> +	return ffa_to_std_errno(ffa_errno);
> +}
> +
> +/* FF-A driver operations (used by clients for communicating with FF-A)*/
> +
> +/**
> + * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
> + *	@uuid_str: pointer to the UUID string
> + *	@sp_count: address of the variable containing the number of partitions matching the UUID
> + *			 The variable is set by the driver
> + *	@sp_descs: address of the descriptors of the partitions matching the UUID
> + *			 The address is set by the driver
> + *
> + * Driver operation for FFA_PARTITION_INFO_GET.
> + * Please see ffa_get_partitions_info_hdlr() description for more details.
> + *
> + * Return:
> + *
> + * @sp_count: the number of partitions
> + * @sp_descs: address of the partitions descriptors
> + *
> + * On success 0 is returned. Otherwise, failure
> + */
> +int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
> +			   u32 *sp_count, struct ffa_partition_desc **sp_descs)
> +{
> +	struct ffa_bus_ops *ops = ffa_get_ops(dev);
> +
> +	if (!ops->partition_info_get)
> +		return -ENOSYS;
> +
> +	return ops->partition_info_get(dev, uuid_str, sp_count, sp_descs);
> +}
> +
> +/**
> + * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
> + * @dev: The FF-A bus device
> + * @dst_part_id: destination partition ID
> + * @msg: pointer to the message data preallocated by the client (in/out)
> + * @is_smc64: select 64-bit or 32-bit FF-A ABI
> + *
> + * Driver operation for FFA_MSG_SEND_DIRECT_{REQ,RESP}.
> + * Please see ffa_msg_send_direct_req_hdlr() description for more details.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
> +			  struct ffa_send_direct_data *msg, bool is_smc64)
> +{
> +	struct ffa_bus_ops *ops = ffa_get_ops(dev);
> +
> +	if (!ops->sync_send_receive)
> +		return -ENOSYS;
> +
> +	return ops->sync_send_receive(dev, dst_part_id, msg, is_smc64);
> +}
> +
> +/**
> + * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
> + * @dev: The FF-A bus device
> + *
> + * Driver operation for FFA_RXTX_UNMAP.
> + * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_rxtx_unmap(struct udevice *dev)
> +{
> +	struct ffa_bus_ops *ops = ffa_get_ops(dev);
> +
> +	if (!ops->rxtx_unmap)
> +		return -ENOSYS;
> +
> +	return ops->rxtx_unmap(dev);
> +}
> +
> +/**
> + * ffa_do_probe() - probing FF-A framework
> + * @dev:	the FF-A bus device (arm_ffa)
> + *
> + * Probing is triggered on demand by clients searching for the uclass.
> + * At probe level the following actions are done:
> + *	- saving the FF-A framework version in uc_priv
> + *	- querying from secure world the u-boot endpoint ID
> + *	- querying from secure world the supported features of FFA_RXTX_MAP
> + *	- mapping the RX/TX buffers
> + *	- querying from secure world all the partitions information
> + *
> + * All data queried from secure world is saved in uc_priv.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static int ffa_do_probe(struct udevice *dev)
> +{
> +	int ret;
> +
> +	ret = ffa_get_version_hdlr(dev);
> +	if (ret)
> +		return ret;
> +
> +	ret = ffa_get_endpoint_id(dev);
> +	if (ret)
> +		return ret;
> +
> +	ret = ffa_get_rxtx_map_features_hdlr(dev);
> +	if (ret)
> +		return ret;
> +
> +	ret = ffa_map_rxtx_buffers_hdlr(dev);
> +	if (ret)
> +		return ret;
> +
> +	ret = ffa_cache_partitions_info(dev);
> +	if (ret) {
> +		ffa_unmap_rxtx_buffers_hdlr(dev);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +UCLASS_DRIVER(ffa) = {
> +	.name			= "ffa",
> +	.id			= UCLASS_FFA,
> +	.pre_probe		= ffa_do_probe,
> +	.pre_remove		= ffa_unmap_rxtx_buffers_hdlr,
> +	.per_device_auto	= sizeof(struct ffa_priv)
> +};
> diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
> new file mode 100644
> index 0000000000..68df75bd9e
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/arm-ffa.c
> @@ -0,0 +1,104 @@
> +// 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 <arm_ffa_priv.h>
> +#include <dm.h>
> +#include <log.h>
> +#include <asm/global_data.h>
> +#include <dm/device-internal.h>
> +#include <linux/errno.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/**
> + * 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 low level SMC assembly function
> + */
> +void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
> +{
> +	arm_smccc_1_2_smc(&args, res);
> +}
> +
> +/**
> + * arm_ffa_discover() - perform FF-A discovery
> + * @dev: The Arm FF-A bus device (arm_ffa)
> + * 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:
> + *
> + * true on success. Otherwise, false.
> + */
> +static bool arm_ffa_discover(struct udevice *dev)
> +{
> +	int ret;
> +
> +	log_info("Arm FF-A framework discovery\n");
> +
> +	ret = ffa_get_version_hdlr(dev);
> +	if (ret)
> +		return false;
> +
> +	return true;
> +}
> +
> +/**
> + * arm_ffa_is_supported() - FF-A bus discovery callback
> + * @invoke_fn: legacy SMC invoke function (not used)
> + *
> + * Perform FF-A discovery by calling arm_ffa_discover().
> + * Discovery is performed by querying the FF-A framework version from
> + * secure world using the FFA_VERSION ABI.
> + *
> + * The FF-A driver is registered as an SMCCC feature driver. So, features discovery
> + * callbacks are called by the PSCI driver (PSCI device is the SMCCC features
> + * root device).
> + *
> + * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
> + * So, the legacy SMC invocation is not used.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +static bool arm_ffa_is_supported(void (*invoke_fn)(ulong a0, ulong a1,
> +						   ulong a2, ulong a3,
> +						   ulong a4, ulong a5,
> +						   ulong a6, ulong a7,
> +						   struct arm_smccc_res *res))
> +{
> +	return arm_ffa_discover(NULL);
> +}
> +
> +/* Arm FF-A driver operations */
> +
> +static const struct ffa_bus_ops 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,
> +};
> +
> +/* Registering the FF-A driver as an SMCCC feature driver */
> +
> +ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
> +	.driver_name = FFA_DRV_NAME,
> +	.is_supported = arm_ffa_is_supported,
> +};
> +
> +/* Declaring the FF-A driver under UCLASS_FFA */
> +
> +U_BOOT_DRIVER(arm_ffa) = {
> +	.name		= FFA_DRV_NAME,
> +	.id		= UCLASS_FFA,
> +	.flags		= DM_REMOVE_OS_PREPARE,
> +	.ops		= &ffa_ops,
> +};
> diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> new file mode 100644
> index 0000000000..4338f9c9b1
> --- /dev/null
> +++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
> @@ -0,0 +1,14 @@
> +/* 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/include/arm_ffa.h b/include/arm_ffa.h
> new file mode 100644
> index 0000000000..db9b1be995
> --- /dev/null
> +++ b/include/arm_ffa.h
> @@ -0,0 +1,213 @@
> +/* 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 __ARM_FFA_H
> +#define __ARM_FFA_H
> +
> +#include <linux/printk.h>
> +
> +/*
> + * This header is public. It can be used by clients to access
> + * data structures and definitions they need
> + */
> +
> +/*
> + * struct ffa_partition_info - Partition information descriptor
> + * @id:	Partition ID
> + * @exec_ctxt:	Execution context count
> + * @properties:	Partition properties
> + *
> + * Data structure containing information about partitions instantiated in the system
> + * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
> + */
> +struct ffa_partition_info {
> +	u16 id;
> +	u16 exec_ctxt;
> +/* partition supports receipt of direct requests */
> +#define FFA_PARTITION_DIRECT_RECV	BIT(0)
> +/* partition can send direct requests. */
> +#define FFA_PARTITION_DIRECT_SEND	BIT(1)
> +/* partition can send and receive indirect messages. */
> +#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
> +	u32 properties;
> +};
> +
> +/*
> + * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
> + * @a1-4:	32-bit words access to the UUID data
> + *
> + */
> +struct ffa_partition_uuid {
> +	u32 a1; /* w1 */
> +	u32 a2; /* w2 */
> +	u32 a3; /* w3 */
> +	u32 a4; /* w4 */
> +};
> +
> +/**
> + * struct ffa_partition_desc - the secure partition descriptor
> + * @info:	partition information
> + * @sp_uuid:	the secure partition UUID
> + *
> + * Each partition has its descriptor containing the partitions information and the UUID
> + */
> +struct ffa_partition_desc {
> +	struct ffa_partition_info info;
> +	struct ffa_partition_uuid sp_uuid;
> +};
> +
> +/*
> + * struct ffa_send_direct_data - Data structure hosting the data
> + *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * @data0-4:	Data read/written from/to x3-x7 registers
> + *
> + * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
> + * or read from FFA_MSG_SEND_DIRECT_RESP
> + */
> +
> +/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
> +struct ffa_send_direct_data {
> +	ulong data0; /* w3/x3 */
> +	ulong data1; /* w4/x4 */
> +	ulong data2; /* w5/x5 */
> +	ulong data3; /* w6/x6 */
> +	ulong data4; /* w7/x7 */
> +};
> +
> +struct udevice;
> +
> +/**
> + * struct ffa_bus_ops - Operations for FF-A
> + * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
> + * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
> + * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
> + *
> + * The data structure providing all the operations supported by the driver.
> + * This structure is EFI runtime resident.
> + */
> +struct ffa_bus_ops {
> +	int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
> +				  u32 *sp_count, struct ffa_partition_desc **sp_descs);
> +	int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
> +				 struct ffa_send_direct_data *msg,
> +				 bool is_smc64);
> +	int (*rxtx_unmap)(struct udevice *dev);
> +};
> +
> +#define ffa_get_ops(dev)        ((struct ffa_bus_ops *)(dev)->driver->ops)
> +
> +/**
> + * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
> + * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
> + */
> +int ffa_rxtx_unmap(struct udevice *dev);
> +
> +/**
> + * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
> + * @dev: The arm_ffa bus device
> + *
> + * This function implements FFA_RXTX_UNMAP FF-A function
> + * to unmap the RX/TX buffers
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev);
> +
> +/**
> + * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
> + * Please see ffa_msg_send_direct_req_hdlr() description for more details.
> + */
> +int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
> +			  struct ffa_send_direct_data *msg, bool is_smc64);
> +
> +/**
> + * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
> + * @dev: The arm_ffa bus device
> + * @dst_part_id: destination partition ID
> + * @msg: pointer to the message data preallocated by the client (in/out)
> + * @is_smc64: select 64-bit or 32-bit FF-A ABI
> + *
> + * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + * FF-A functions.
> + *
> + * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
> + * The response from the secure partition is handled by reading the
> + * FFA_MSG_SEND_DIRECT_RESP arguments.
> + *
> + * The maximum size of the data that can be exchanged is 40 bytes which is
> + * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
> + * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
> +				 struct ffa_send_direct_data *msg, bool is_smc64);
> +
> +/**
> + * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
> + * Please see ffa_get_partitions_info_hdlr() description for more details.
> + */
> +int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
> +			   u32 *sp_count, struct ffa_partition_desc **sp_descs);
> +
> +/**
> + * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
> + *	@uuid_str: pointer to the UUID string
> + *	@sp_count: address of the variable containing the number of partitions matching the UUID
> + *			 The variable is set by the driver
> + *	@sp_descs: address of the descriptors of the partitions matching the UUID
> + *			 The address is set by the driver
> + *
> + * Return the number of partitions and their descriptors matching the UUID
> + *
> + * Query the secure partition data from uc_priv.
> + * If not found, invoke FFA_PARTITION_INFO_GET
> + * FF-A function to query the partition information from secure world.
> + *
> + * A client of the FF-A driver should know the UUID of the service it wants to
> + * access. It should use the UUID to request the FF-A driver to provide the
> + * partition(s) information of the service. The FF-A driver uses
> + * PARTITION_INFO_GET to obtain this information. This is implemented through
> + * ffa_get_partitions_info_hdlr() function.
> + * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
> + * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
> + * They are not saved (already done). We only update the UUID in the cached area.
> + * This assumes that partitions data does not change in the secure world.
> + * Otherwise u-boot will have an outdated partition data. The benefit of caching
> + * the information in the FF-A driver is to accommodate discovery after
> + * ExitBootServices().
> + *
> + * Return:
> + *
> + * @sp_count: the number of partitions
> + * @sp_descs: address of the partitions descriptors
> + *
> + * On success 0 is returned. Otherwise, failure
> + */
> +int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
> +				 u32 *sp_count, struct ffa_partition_desc **sp_descs);
> +
> +struct ffa_priv;
> +
> +/**
> + * ffa_set_smc_conduit() - Set the SMC conduit
> + * @dev: The FF-A bus device
> + *
> + * Selects the SMC conduit by setting the FF-A ABI invoke function.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_set_smc_conduit(struct udevice *dev);
> +
> +#endif
> diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
> new file mode 100644
> index 0000000000..d564c33c64
> --- /dev/null
> +++ b/include/arm_ffa_priv.h
> @@ -0,0 +1,246 @@
> +/* 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 __ARM_FFA_PRV_H
> +#define __ARM_FFA_PRV_H
> +
> +#include <mapmem.h>
> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
> +
> +/* This header is exclusively used by the FF-A Uclass and FF-A driver(s) */
> +
> +/* Arm FF-A driver name */
> +#define FFA_DRV_NAME "arm_ffa"
> +
> +/* The FF-A SMC function definitions */
> +
> +#if CONFIG_IS_ENABLED(SANDBOX)
> +
> +/* Providing Arm SMCCC declarations to sandbox */
> +
> +/**
> + * struct sandbox_smccc_1_2_regs - emulated SMC call arguments or results
> + * @a0-a17 argument values from registers 0 to 17
> + */
> +struct sandbox_smccc_1_2_regs {
> +	ulong a0;
> +	ulong a1;
> +	ulong a2;
> +	ulong a3;
> +	ulong a4;
> +	ulong a5;
> +	ulong a6;
> +	ulong a7;
> +	ulong a8;
> +	ulong a9;
> +	ulong a10;
> +	ulong a11;
> +	ulong a12;
> +	ulong a13;
> +	ulong a14;
> +	ulong a15;
> +	ulong a16;
> +	ulong a17;
> +};
> +
> +typedef struct sandbox_smccc_1_2_regs ffa_value_t;
> +
> +#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))
> +
> +#else
> +/* CONFIG_ARM64 */
> +#include <linux/arm-smccc.h>
> +typedef struct arm_smccc_1_2_regs ffa_value_t;
> +#endif
> +
> +/* Defining the function pointer type for the function executing the FF-A ABIs */
> +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)
> +#define MINOR_VERSION_MASK		GENMASK(15, 0)
> +#define GET_FFA_MAJOR_VERSION(x)		\
> +				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
> +#define GET_FFA_MINOR_VERSION(x)		\
> +				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
> +#define PACK_VERSION_INFO(major, minor)			\
> +	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
> +	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
> +
> +#define FFA_MAJOR_VERSION		(1)
> +#define FFA_MINOR_VERSION		(0)
> +#define FFA_VERSION_1_0		\
> +			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
> +
> +/* Endpoint ID mask (u-boot endpoint ID) */
> +
> +#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
> +#define GET_SELF_ENDPOINT_ID(x)		\
> +			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
> +
> +#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
> +#define PREP_SELF_ENDPOINT_ID(x)		\
> +			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
> +
> +/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
> +
> +#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
> +#define PREP_PART_ENDPOINT_ID(x)		\
> +			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
> +
> +/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */
> +
> +#define FFA_SMC(calling_convention, func_num)				\
> +	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
> +			   ARM_SMCCC_OWNER_STANDARD, (func_num))
> +
> +#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
> +#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
> +
> +enum ffa_abis {
> +	FFA_ERROR                 = 0x60,
> +	FFA_SUCCESS               = 0x61,
> +	FFA_INTERRUPT             = 0x62,
> +	FFA_VERSION               = 0x63,
> +	FFA_FEATURES              = 0x64,
> +	FFA_RX_RELEASE            = 0x65,
> +	FFA_RXTX_MAP              = 0x66,
> +	FFA_RXTX_UNMAP            = 0x67,
> +	FFA_PARTITION_INFO_GET    = 0x68,
> +	FFA_ID_GET                = 0x69,
> +	FFA_RUN                   = 0x6d,
> +	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
> +	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
> +
> +	/* To be updated when adding new FFA IDs */
> +	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
> +	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
> +};
> +
> +enum ffa_abi_errcode {
> +	NOT_SUPPORTED = 1,
> +	INVALID_PARAMETERS,
> +	NO_MEMORY,
> +	BUSY,
> +	INTERRUPTED,
> +	DENIED,
> +	RETRY,
> +	ABORTED,
> +	MAX_NUMBER_FFA_ERR
> +};
> +
> +extern int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR];
> +
> +/* Container structure and helper macros to map between an FF-A error and relevant error log */
> +struct ffa_abi_errmap {
> +	char *err_str[MAX_NUMBER_FFA_ERR];
> +};
> +
> +#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
> +#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
> +
> +/**
> + * enum ffa_rxtx_buf_sizes - minimum sizes supported
> + * for the RX/TX buffers
> + */
> +enum ffa_rxtx_buf_sizes {
> +	RXTX_4K,
> +	RXTX_64K,
> +	RXTX_16K
> +};
> +
> +/**
> + * struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses
> + * @rxbuf:	virtual address of the RX buffer
> + * @txbuf:	virtual address of the TX buffer
> + * @rxtx_min_pages:	RX/TX buffers minimum size in pages
> + *
> + * Hosts the virtual addresses of the mapped RX/TX buffers
> + * These addresses are used by the FF-A functions that use the RX/TX buffers
> + */
> +struct ffa_rxtxpair {
> +	void *rxbuf; /* Virtual address returned by memalign */
> +	void *txbuf; /* Virtual address returned by memalign */
> +	size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */
> +};
> +
> +struct ffa_partition_desc;
> +
> +/**
> + * struct ffa_partitions - descriptors for all secure partitions
> + * @count:	The number of partitions descriptors
> + * @descs	The partitions descriptors table
> + *
> + * Contains the partitions descriptors table
> + */
> +struct ffa_partitions {
> +	u32 count;
> +	struct ffa_partition_desc *descs; /* Virtual address */
> +};
> +
> +/**
> + * struct ffa_priv - the driver private data structure
> + *
> + * @fwk_version:	FF-A framework version
> + * @emul:	FF-A sandbox emulator
> + * @id:	u-boot endpoint ID
> + * @partitions:	The partitions descriptors structure
> + * @pair:	The RX/TX buffers pair
> + *
> + * The device private data structure containing all the
> + * data read from secure world.
> + */
> +struct ffa_priv {
> +	u32 fwk_version;
> +	struct udevice *emul;
> +	u16 id;
> +	struct ffa_partitions partitions;
> +	struct ffa_rxtxpair pair;
> +};
> +
> +/**
> + * ffa_get_version_hdlr() - FFA_VERSION handler function
> + * @dev: The FF-A bus device
> + *
> + * Implement FFA_VERSION FF-A function
> + * to get from the secure world the FF-A framework version
> + * FFA_VERSION is used to discover the FF-A framework.
> + *
> + * Return:
> + *
> + * 0 on success. Otherwise, failure
> + */
> +int ffa_get_version_hdlr(struct udevice *dev);
> +
> +/**
> + * 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 low level SMC implementation.
> + * This function should be implemented by the user driver.
> + */
> +void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res);
> +
> +#endif
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 307ad6931c..3c6af2e3d2 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -4,6 +4,11 @@
>   *
>   * (C) Copyright 2012
>   * Pavel Herrmann <morpheus.ibis@gmail.com>
> + *
> + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *
> + * Authors:
> + *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #ifndef _DM_UCLASS_ID_H
> @@ -57,6 +62,7 @@ enum uclass_id {
>  	UCLASS_ETH,		/* Ethernet device */
>  	UCLASS_ETH_PHY,		/* Ethernet PHY device */
>  	UCLASS_EXTCON,		/* External Connector Class */
> +	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
>  	UCLASS_FIRMWARE,	/* Firmware */
>  	UCLASS_FPGA,		/* FPGA device */
>  	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
> -- 
> 2.25.1
> 
Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
  2023-07-26 19:39                                                                                                                                                   ` Tom Rini
@ 2023-07-27  9:58                                                                                                                                                   ` Ilias Apalodimas
  2023-07-27 15:28                                                                                                                                                     ` Gowtham Suresh Kumar
  2023-07-27 11:27                                                                                                                                                   ` Ilias Apalodimas
  2 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-07-27  9:58 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: trini, nd, u-boot, Gowtham Suresh Kumar, Simon Glass, Jens Wiklander

On Wed, Jul 26, 2023 at 10:45:02AM +0100, Abdellatif El Khlifi wrote:
> Add MM communication support using FF-A transport
> 
> This feature allows accessing MM partitions services through
> EFI MM communication protocol. MM partitions such as StandAlonneMM
> or smm-gateway secure partitions which reside in secure world.
> 
> An MM shared buffer and a door bell event are used to exchange
> the data.
> 
> The data is used by EFI services such as GetVariable()/SetVariable()
> and copied from the communication buffer to the MM shared buffer.
> 
> The secure partition is notified about availability of data in the
> MM shared buffer by an FF-A message (door bell).
> 
> On such event, MM SP can read the data and updates the MM shared
> buffer with the response data.
> 
> The response data is copied back to the communication buffer and
> consumed by the EFI subsystem.
> 
> MM communication protocol supports FF-A 64-bit direct messaging.
> 
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>

Is there a public record of thise tested-by?  If not please don't inject
them like this or have Gowtham respond on the mailing list 

Thanks
/Ilias
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Cc: Jens Wiklander <jens.wiklander@linaro.org>
> 
> ---
> 
> Changelog:
> ===============
> 
> v16:
> 
> * lib/efi_loader/Kconfig:
>    rather than automatically selecting OPTEE and ARM_FFA_TRANSPORT configs by
>    EFI_MM_COMM_TEE, set them as dependencies (Otherwise FF-A will be automatically
>    enabled for boards that don't need it).
> 
> v15:
> 
> Simon:
> 
> * replace FFA_SHARED_MM_BUFFER_* defines with configs
> 
> v14:
> 
> Ilias:
> 
> * drop truncating var_payload->size when using FF-A
> * map the MM SP return codes to errnos
> 
> v13:
> 
> * remove FF-A and Optee ifdefs
> 
> v12:
> 
> * drop use of calloc when querying SPs
> * address nits
> 
> v11:
> 
> * rename select_ffa_mm_comms() to select_mm_comms()
> * improve the logic of MM transport selection in mm_communicate()
> * addressing nits
> 
> v10:
> 
> * use the FF-A driver Uclass operations
> * use uclass_first_device()
> * addressing nits
> 
> v9: align how FF-A is used with FF-A discovery through DM
> 
> v8:
> 
> * isolate the compilation choices between FF-A and OP-TEE
> * update partition_info_get() second argument to be an SP count
> * pass NULL device pointer to the FF-A bus discovery and operations
> 
> v7:
> 
> * set the MM door bell event to use 64-bit direct messaging
> * issue a compile time error when one of these macros are not found :
>   FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
> * make mm_sp_svc_uuid static
> * replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
> * improve use of unmap_sysmem() in ffa_mm_communicate()
> 
> v6:
> 
> * add FF-A runtime discovery at MM communication level
> * drop EFI runtime support for FF-A MM communication
> * revert the changes in include/mm_communication.h for
>   efi_mm_communicate_header and smm_variable_access structures
> 
> v4:
> 
> * use the new FF-A driver interfaces
> * discover MM partitions at runtime
> * copy FF-A driver private data to EFI runtime section at
>   ExitBootServices()
> * drop use of FFA_ERR_STAT_SUCCESS error code
> * replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
>   in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
> * revert the error log in mm_communicate() in case of failure
> * remove packed attribute from efi_mm_communicate_header and
>   smm_variable_communicate_header
> 
> v2:
> 
> * set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings
> 
> v1:
> 
> * introduce FF-A MM communication
> 
> include/mm_communication.h        |  13 ++
>  lib/efi_loader/Kconfig            |  44 ++++-
>  lib/efi_loader/efi_variable_tee.c | 257 +++++++++++++++++++++++++++++-
>  3 files changed, 307 insertions(+), 7 deletions(-)
> 
> diff --git a/include/mm_communication.h b/include/mm_communication.h
> index e65fbde60d..f17847583b 100644
> --- a/include/mm_communication.h
> +++ b/include/mm_communication.h
> @@ -6,6 +6,9 @@
>   *  Copyright (c) 2017, Intel Corporation. All rights reserved.
>   *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
>   *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
> + *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *    Authors:
> + *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #ifndef _MM_COMMUNICATION_H_
> @@ -13,6 +16,9 @@
>  
>  #include <part_efi.h>
>  
> +/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
> +#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
> +
>  /*
>   * Interface to the pseudo Trusted Application (TA), which provides a
>   * communication channel with the Standalone MM (Management Mode)
> @@ -248,4 +254,11 @@ struct smm_variable_var_check_property {
>  	u16                       name[];
>  };
>  
> +/* supported MM transports */
> +enum mm_comms_select {
> +	MM_COMMS_UNDEFINED,
> +	MM_COMMS_FFA,
> +	MM_COMMS_OPTEE
> +};
> +
>  #endif /* _MM_COMMUNICATION_H_ */
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index c5835e6ef6..8fbadb9201 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
>  	  stored as file /ubootefi.var on the EFI system partition.
>  
>  config EFI_MM_COMM_TEE
> -	bool "UEFI variables storage service via OP-TEE"
> -	depends on OPTEE
> +	bool "UEFI variables storage service via the trusted world"
> +	depends on OPTEE && ARM_FFA_TRANSPORT
>  	help
> +	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
> +	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> +	  When using the u-boot FF-A  driver any MM SP is supported.
> +
>  	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
>  	  variable related operations to that. The application will verify,
>  	  authenticate and store the variables on an RPMB.
>  
> +	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> +	  operations to the MM SP running in the secure world.
> +	  A door bell mechanism is used to notify the SP when there is data in the shared
> +	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
> +	  the door bell event.
> +
> +config FFA_SHARED_MM_BUF_SIZE
> +	int "Memory size of the shared MM communication buffer"
> +	default 0
> +	depends on EFI_MM_COMM_TEE
> +	help
> +	  This defines the size in bytes of the memory area reserved for the shared
> +	  buffer used for communication between the MM feature in U-Boot and
> +	  the MM SP in secure world.
> +	  The size of the memory region must be a multiple of the size of the maximum
> +	  translation granule size that is specified in the ID_AA64MMFR0_EL1 System register.
> +	  It is assumed that the MM SP knows the size of the shared MM communication buffer.
> +
> +config FFA_SHARED_MM_BUF_OFFSET
> +	int "Data offset in the shared MM communication buffer"
> +	default 0
> +	depends on EFI_MM_COMM_TEE
> +	help
> +	  This defines the offset in bytes of the data read or written to in the shared
> +	  buffer by the MM SP.
> +
> +config FFA_SHARED_MM_BUF_ADDR
> +	hex "Define the address of the shared MM communication buffer"
> +	default 0x0
> +	depends on EFI_MM_COMM_TEE
> +	help
> +	  This defines the address of the shared MM communication buffer
> +	  used for communication between the MM feature in U-Boot and
> +	  the MM SP in secure world.
> +	  It is assumed that the MM SP knows the address of the shared MM communication buffer.
> +
>  config EFI_VARIABLE_NO_STORE
>  	bool "Don't persist non-volatile UEFI variables"
>  	help
> diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> index dfef18435d..5137b871ea 100644
> --- a/lib/efi_loader/efi_variable_tee.c
> +++ b/lib/efi_loader/efi_variable_tee.c
> @@ -4,17 +4,34 @@
>   *
>   *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
>   *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
> + *  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 <cpu_func.h>
> +#include <dm.h>
>  #include <efi.h>
>  #include <efi_api.h>
>  #include <efi_loader.h>
>  #include <efi_variable.h>
> -#include <tee.h>
>  #include <malloc.h>
> +#include <mapmem.h>
>  #include <mm_communication.h>
> +#include <tee.h>
> +
> +/* MM return codes */
> +#define MM_SUCCESS (0)
> +#define MM_NOT_SUPPORTED (-1)
> +#define MM_INVALID_PARAMETER (-2)
> +#define MM_DENIED (-3)
> +#define MM_NO_MEMORY (-5)
>  
> +static const char *mm_sp_svc_uuid = MM_SP_UUID;
> +static u16 mm_sp_id;
>  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
>  static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
>  static efi_uintn_t max_payload_size;	/* func + data */
> @@ -145,16 +162,241 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
>  }
>  
>  /**
> - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
> + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> + *
> + * Notify the MM partition in the trusted world that
> + * data is available in the shared buffer.
> + * This is a blocking call during which trusted world has exclusive access
> + * to the MM shared buffer.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_notify_mm_sp(void)
> +{
> +	struct ffa_send_direct_data msg = {0};
> +	int ret;
> +	int sp_event_ret;
> +	struct udevice *dev;
> +
> +	ret = uclass_first_device_err(UCLASS_FFA, &dev);
> +	if (ret) {
> +		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
> +		return ret;
> +	}
> +
> +	msg.data0 = CONFIG_FFA_SHARED_MM_BUF_OFFSET; /* x3 */
> +
> +	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
> +	if (ret)
> +		return ret;
> +
> +	sp_event_ret = msg.data0; /* x3 */
> +
> +	switch (sp_event_ret) {
> +	case MM_SUCCESS:
> +		ret = 0;
> +		break;
> +	case MM_NOT_SUPPORTED:
> +		ret = -EINVAL;
> +		break;
> +	case MM_INVALID_PARAMETER:
> +		ret = -EPERM;
> +		break;
> +	case MM_DENIED:
> +		ret = -EACCES;
> +		break;
> +	case MM_NO_MEMORY:
> +		ret = -EBUSY;
> +		break;
> +	default:
> +		ret = -EACCES;
> +	}
> +
> +	return ret;
> +}
> +
> +/**
> + * ffa_discover_mm_sp_id() - Query the MM partition ID
> + *
> + * Use the FF-A driver to get the MM partition ID.
> + * If multiple partitions are found, use the first one.
> + * This is a boot time function.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_discover_mm_sp_id(void)
> +{
> +	u32 count = 0;
> +	int ret;
> +	struct ffa_partition_desc *descs;
> +	struct udevice *dev;
> +
> +	ret = uclass_first_device_err(UCLASS_FFA, &dev);
> +	if (ret) {
> +		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
> +		return ret;
> +	}
> +
> +	/* Ask the driver to fill the buffer with the SPs info */
> +	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, &descs);
> +	if (ret) {
> +		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
> +		return ret;
> +	}
> +
> +	/* MM SPs found , use the first one */
> +
> +	mm_sp_id = descs[0].info.id;
> +
> +	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
> +
> +	return 0;
> +}
> +
> +/**
> + * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
> + * @comm_buf:		locally allocated communication buffer used for rx/tx
> + * @dsize:				communication buffer size
> + *
> + * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
> + * that there is data to read from the shared buffer.
> + * Communication with the MM SP is performed using FF-A transport.
> + * On the event, MM SP can read the data from the buffer and
> + * update the MM shared buffer with response data.
> + * The response data is copied back to the communication buffer.
> + *
> + * Return:
> + *
> + * EFI status code
> + */
> +static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
> +{
> +	ulong tx_data_size;
> +	int ffa_ret;
> +	efi_status_t efi_ret;
> +	struct efi_mm_communicate_header *mm_hdr;
> +	void *virt_shared_buf;
> +
> +	if (!comm_buf)
> +		return EFI_INVALID_PARAMETER;
> +
> +	/* Discover MM partition ID at boot time */
> +	if (!mm_sp_id && ffa_discover_mm_sp_id()) {
> +		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
> +		return EFI_UNSUPPORTED;
> +	}
> +
> +	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> +	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
> +
> +	if (comm_buf_size != tx_data_size || tx_data_size > CONFIG_FFA_SHARED_MM_BUF_SIZE)
> +		return EFI_INVALID_PARAMETER;
> +
> +	/* Copy the data to the shared buffer */
> +
> +	virt_shared_buf = map_sysmem((phys_addr_t)CONFIG_FFA_SHARED_MM_BUF_ADDR, 0);
> +	memcpy(virt_shared_buf, comm_buf, tx_data_size);
> +
> +	/*
> +	 * The secure world might have cache disabled for
> +	 * the device region used for shared buffer (which is the case for Optee).
> +	 * In this case, the secure world reads the data from DRAM.
> +	 * Let's flush the cache so the DRAM is updated with the latest data.
> +	 */
> +#ifdef CONFIG_ARM64
> +	invalidate_dcache_all();
> +#endif
> +
> +	/* Announce there is data in the shared buffer */
> +
> +	ffa_ret = ffa_notify_mm_sp();
> +
> +	switch (ffa_ret) {
> +	case 0: {
> +		ulong rx_data_size;
> +		/* Copy the MM SP response from the shared buffer to the communication buffer */
> +		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> +			sizeof(efi_guid_t) +
> +			sizeof(size_t);
> +
> +		if (rx_data_size > comm_buf_size) {
> +			efi_ret = EFI_OUT_OF_RESOURCES;
> +			break;
> +		}
> +
> +		memcpy(comm_buf, virt_shared_buf, rx_data_size);
> +		efi_ret = EFI_SUCCESS;
> +		break;
> +	}
> +	case -EINVAL:
> +		efi_ret = EFI_DEVICE_ERROR;
> +		break;
> +	case -EPERM:
> +		efi_ret = EFI_INVALID_PARAMETER;
> +		break;
> +	case -EACCES:
> +		efi_ret = EFI_ACCESS_DENIED;
> +		break;
> +	case -EBUSY:
> +		efi_ret = EFI_OUT_OF_RESOURCES;
> +		break;
> +	default:
> +		efi_ret = EFI_ACCESS_DENIED;
> +	}
> +
> +	unmap_sysmem(virt_shared_buf);
> +	return efi_ret;
> +}
> +
> +/**
> + * get_mm_comms() - detect the available MM transport
> + *
> + * Make sure the FF-A bus is probed successfully
> + * which means FF-A communication with secure world works and ready
> + * for use.
> + *
> + * If FF-A bus is not ready, use OPTEE comms.
> + *
> + * Return:
> + *
> + * MM_COMMS_FFA or MM_COMMS_OPTEE
> + */
> +static enum mm_comms_select get_mm_comms(void)
> +{
> +	struct udevice *dev;
> +	int ret;
> +
> +	ret = uclass_first_device_err(UCLASS_FFA, &dev);
> +	if (ret) {
> +		log_err("EFI: Cannot find FF-A bus device, trying Optee comms\n");
> +		return MM_COMMS_OPTEE;
> +	}
> +
> +	return MM_COMMS_FFA;
> +}
> +
> +/**
> + * mm_communicate() - Adjust the communication buffer to the MM SP and send
>   * it to OP-TEE
>   *
> - * @comm_buf:		locally allocted communcation buffer
> + * @comm_buf:		locally allocated communication buffer
>   * @dsize:		buffer size
> + *
> + * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
> + * The comm_buf format is the same for both partitions.
> + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> + * When using the u-boot FF-A  driver, any MM SP is supported.
> + *
>   * Return:		status code
>   */
>  static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  {
>  	efi_status_t ret;
> +	enum mm_comms_select mm_comms;
>  	struct efi_mm_communicate_header *mm_hdr;
>  	struct smm_variable_communicate_header *var_hdr;
>  
> @@ -162,7 +404,12 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
>  	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
>  
> -	ret = optee_mm_communicate(comm_buf, dsize);
> +	mm_comms = get_mm_comms();
> +	if (mm_comms == MM_COMMS_FFA)
> +		ret = ffa_mm_communicate(comm_buf, dsize);
> +	else
> +		ret = optee_mm_communicate(comm_buf, dsize);
> +
>  	if (ret != EFI_SUCCESS) {
>  		log_err("%s failed!\n", __func__);
>  		return ret;
> @@ -697,7 +944,7 @@ void efi_variables_boot_exit_notify(void)
>  		ret = EFI_NOT_FOUND;
>  
>  	if (ret != EFI_SUCCESS)
> -		log_err("Unable to notify StMM for ExitBootServices\n");
> +		log_err("Unable to notify the MM partition for ExitBootServices\n");
>  	free(comm_buf);
>  
>  	/*
> -- 
> 2.25.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
  2023-07-26 19:39                                                                                                                                                   ` Tom Rini
  2023-07-27  9:58                                                                                                                                                   ` Ilias Apalodimas
@ 2023-07-27 11:27                                                                                                                                                   ` Ilias Apalodimas
  2023-07-27 12:36                                                                                                                                                     ` Abdellatif El Khlifi
  2 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-07-27 11:27 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: trini, nd, u-boot, Gowtham Suresh Kumar, Simon Glass, Jens Wiklander

Hi Abdellatif, 

[...]

> +}
> +
> +/**
> + * get_mm_comms() - detect the available MM transport
> + *
> + * Make sure the FF-A bus is probed successfully
> + * which means FF-A communication with secure world works and ready
> + * for use.
> + *
> + * If FF-A bus is not ready, use OPTEE comms.
> + *
> + * Return:
> + *
> + * MM_COMMS_FFA or MM_COMMS_OPTEE
> + */
> +static enum mm_comms_select get_mm_comms(void)
> +{
> +	struct udevice *dev;
> +	int ret;
> +
> +	ret = uclass_first_device_err(UCLASS_FFA, &dev);
> +	if (ret) {
> +		log_err("EFI: Cannot find FF-A bus device, trying Optee comms\n");

This isn't an error.  If you mark it as one it will pollute the console
every time you try to decide if it's an FFA or an SMC call to op-tee.  So
either remote this or switch it to log_debug or something.  While at it,
any reason why we need to keep probing the ffa bus?  Can't we just run this
once during init?

> +		return MM_COMMS_OPTEE;
> +	}
> +
> +	return MM_COMMS_FFA;
> +}
> +
> +/**
> + * mm_communicate() - Adjust the communication buffer to the MM SP and send
>   * it to OP-TEE
>   *
> - * @comm_buf:		locally allocted communcation buffer
> + * @comm_buf:		locally allocated communication buffer
>   * @dsize:		buffer size
> + *
> + * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
> + * The comm_buf format is the same for both partitions.
> + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> + * When using the u-boot FF-A  driver, any MM SP is supported.
> + *
>   * Return:		status code
>   */
>  static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  {
>  	efi_status_t ret;
> +	enum mm_comms_select mm_comms;
>  	struct efi_mm_communicate_header *mm_hdr;
>  	struct smm_variable_communicate_header *var_hdr;
>  
> @@ -162,7 +404,12 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
>  	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
>  
> -	ret = optee_mm_communicate(comm_buf, dsize);
> +	mm_comms = get_mm_comms();
> +	if (mm_comms == MM_COMMS_FFA)
> +		ret = ffa_mm_communicate(comm_buf, dsize);
> +	else
> +		ret = optee_mm_communicate(comm_buf, dsize);
> +
>  	if (ret != EFI_SUCCESS) {
>  		log_err("%s failed!\n", __func__);
>  		return ret;
> @@ -697,7 +944,7 @@ void efi_variables_boot_exit_notify(void)
>  		ret = EFI_NOT_FOUND;
>  
>  	if (ret != EFI_SUCCESS)
> -		log_err("Unable to notify StMM for ExitBootServices\n");
> +		log_err("Unable to notify the MM partition for ExitBootServices\n");
>  	free(comm_buf);
>  
>  	/*
> -- 
> 2.25.1
> 

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-27 11:27                                                                                                                                                   ` Ilias Apalodimas
@ 2023-07-27 12:36                                                                                                                                                     ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27 12:36 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: sjg, trini, u-boot, nd

Hi Ilias,

On Thu, Jul 27, 2023 at 02:27:21PM +0300, Ilias Apalodimas wrote:
> Hi Abdellatif, 
> 
> [...]
> 
> > +}
> > +
> > +/**
> > + * get_mm_comms() - detect the available MM transport
> > + *
> > + * Make sure the FF-A bus is probed successfully
> > + * which means FF-A communication with secure world works and ready
> > + * for use.
> > + *
> > + * If FF-A bus is not ready, use OPTEE comms.
> > + *
> > + * Return:
> > + *
> > + * MM_COMMS_FFA or MM_COMMS_OPTEE
> > + */
> > +static enum mm_comms_select get_mm_comms(void)
> > +{
> > +	struct udevice *dev;
> > +	int ret;
> > +
> > +	ret = uclass_first_device_err(UCLASS_FFA, &dev);
> > +	if (ret) {
> > +		log_err("EFI: Cannot find FF-A bus device, trying Optee comms\n");
> 
> This isn't an error.  If you mark it as one it will pollute the console
> every time you try to decide if it's an FFA or an SMC call to op-tee.  So
> either remote this or switch it to log_debug or something.  While at it,

Good point, thanks. I'll replace it with log_debug.

> any reason why we need to keep probing the ffa bus?  Can't we just run this
> once during init?
> 

Probing the FF-A bus is only done once. Subsequent calls to uclass_first_device_err()
will not probe again, they only return the dev.
An existing dev means FF-A bus is up and running. Failure to find a dev means either FF-A discovery failed
(e.g: FF-A no implemented in secure world), or probing failed (e.g: a setup FF-A ABI failed).

Cheers,
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-27  9:34                                                                                                                                                     ` Abdellatif El Khlifi
@ 2023-07-27 13:30                                                                                                                                                       ` Tom Rini
  0 siblings, 0 replies; 478+ messages in thread
From: Tom Rini @ 2023-07-27 13:30 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: gowtham.sureshkumar, ilias.apalodimas, jens.wiklander,
	meenakshi.aggarwal, nd, priyanka.jain, sjg, u-boot, wasim.khan

[-- Attachment #1: Type: text/plain, Size: 3109 bytes --]

On Thu, Jul 27, 2023 at 10:34:50AM +0100, Abdellatif El Khlifi wrote:
> Hi Tom,
> 
> On Wed, Jul 26, 2023 at 03:39:12PM -0400, Tom Rini wrote:
> > On Wed, Jul 26, 2023 at 10:45:02AM +0100, Abdellatif El Khlifi wrote:
> > 
> > > Add MM communication support using FF-A transport
> > > 
> > > This feature allows accessing MM partitions services through
> > > EFI MM communication protocol. MM partitions such as StandAlonneMM
> > > or smm-gateway secure partitions which reside in secure world.
> > > 
> > > An MM shared buffer and a door bell event are used to exchange
> > > the data.
> > > 
> > > The data is used by EFI services such as GetVariable()/SetVariable()
> > > and copied from the communication buffer to the MM shared buffer.
> > > 
> > > The secure partition is notified about availability of data in the
> > > MM shared buffer by an FF-A message (door bell).
> > > 
> > > On such event, MM SP can read the data and updates the MM shared
> > > buffer with the response data.
> > > 
> > > The response data is copied back to the communication buffer and
> > > consumed by the EFI subsystem.
> > > 
> > > MM communication protocol supports FF-A 64-bit direct messaging.
> > > 
> > > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
> > > Reviewed-by: Simon Glass <sjg@chromium.org>
> > > Cc: Tom Rini <trini@konsulko.com>
> > > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > > Cc: Jens Wiklander <jens.wiklander@linaro.org>
> > 
> > So, at this point in the series we impact lx2160ardb_tfa_stmm which is
> > the only config in the tree prior to this series that sets
> > CONFIG_EFI_MM_COMM_TEE. I'm not going to block this series[1] on
> > updating lx2160ardb_tfa_stmm as well, but I do want to make sure the
> > maintainers there are aware and can update the config to support the
> > current state of this technology.
> > 
> > [1]: https://patchwork.ozlabs.org/project/uboot/list/?series=365876&state=*
> > -- 
> 
> Following a decision made with Ilias, the new MM comms design works as follows:
> 
> - Try to communicate using FF-A bus first
> - If that fails, try to communicate using Optee. So, platforms that don't support FF-A
>   in the Secure side can still use Optee communication
> 
> This is done through the code below [1].
> 
> This logic needs CONFIG_ARM_FFA_TRANSPORT=y in the defconfig.
> 
> I added CONFIG_ARM_FFA_TRANSPORT=y to lx2160ardb_tfa_stmm_defconfig, CONFIG_EFI_MM_COMM_TEE is enabled and it builds fine.
> 
> Is it expected that lx2160ardb_tfa_stmm maintainers add CONFIG_ARM_FFA_TRANSPORT=y to lx2160ardb_tfa_stmm_defconfig ?

Ah, it sounds like the Kconfig logic this patch adds is wrong then. Is
there a use case for ARM_FFA_TRANSPORT without CONFIG_EFI_MM_COMM_TEE=y
? If yes, then it's just that the FF-A related symbols for
EFI_MM_COMM_TEE need to depend on ARM_FFA_TRANSPORT.  If no,
ARM_FFA_TRANSPORT needs to depend on EFI_MM_COMM_TEE (and these new
symbols depend on ARM_FFA_TRANSPORT).

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-27  9:58                                                                                                                                                   ` Ilias Apalodimas
@ 2023-07-27 15:28                                                                                                                                                     ` Gowtham Suresh Kumar
  0 siblings, 0 replies; 478+ messages in thread
From: Gowtham Suresh Kumar @ 2023-07-27 15:28 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: abdellatif.elkhlifi, trini, nd, u-boot, sjg, jens.wiklander

Hi Ilias,

On Thu, Jul 27, 2023 at 12:58:57PM +0300, Ilias Apalodimas wrote:
> On Wed, Jul 26, 2023 at 10:45:02AM +0100, Abdellatif El Khlifi wrote:
> > Add MM communication support using FF-A transport
> > 
> > This feature allows accessing MM partitions services through
> > EFI MM communication protocol. MM partitions such as StandAlonneMM
> > or smm-gateway secure partitions which reside in secure world.
> > 
> > An MM shared buffer and a door bell event are used to exchange
> > the data.
> > 
> > The data is used by EFI services such as GetVariable()/SetVariable()
> > and copied from the communication buffer to the MM shared buffer.
> > 
> > The secure partition is notified about availability of data in the
> > MM shared buffer by an FF-A message (door bell).
> > 
> > On such event, MM SP can read the data and updates the MM shared
> > buffer with the response data.
> > 
> > The response data is copied back to the communication buffer and
> > consumed by the EFI subsystem.
> > 
> > MM communication protocol supports FF-A 64-bit direct messaging.
> > 
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
> 
> Is there a public record of thise tested-by?  If not please don't inject
> them like this or have Gowtham respond on the mailing list 

Yes, we tested the FF-A MM communication on the Corstone-1000 platform.

We ran the UEFI SCT test suite containing EFI setVariable, getVariable and getNextVariable tests which involve FF-A MM communication and all tests are passing with the current changes. 

We made the SCT test reports (part of the ACS results) public following the latest Corstone-1000 release.

Please find the test reports at [1].

Kind regards,
Gowtham Suresh Kumar

[1]: https://gitlab.arm.com/arm-reference-solutions/arm-reference-solutions-test-report/-/tree/master/embedded-a/corstone1000/CORSTONE1000-2023.06/acs_results_fpga.zip


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v17 00/10] introduce Arm FF-A support
  2023-07-26 16:06                                                                                                                                                   ` Tom Rini
@ 2023-07-27 16:07                                                                                                                                                     ` Abdellatif El Khlifi
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                                                                                                                                         ` (9 more replies)
  0 siblings, 10 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27 16:07 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, jens.wiklander, nd, sjg,
	u-boot, Rob Herring, Achin Gupta, Drew Reed, Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].

FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
communicate with each other. A partition could be a VM in the Normal or Secure world, an
application in S-EL0, or a Trusted OS in S-EL1.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

   => dm tree

    Class     Index  Probed  Driver                Name
   -----------------------------------------------------------
   ...
    firmware      0  [ + ]   psci                      |-- psci
    ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
   ...

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

This implementation of the specification provides support for Aarch64.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

    - Discover the presence of secure partitions (SPs) of interest
    - Access an SP's service through communication protocols
      (e.g: EFI MM communication protocol)

The FF-A support provides the following features:

    - Being generic by design and can be used by any Arm 64-bit platform
    - FF-A support can be compiled and used without EFI
    - Support for SMCCCv1.2 x0-x17 registers
    - Support for SMC32 calling convention
    - Support for 32-bit and 64-bit FF-A direct messaging
    - Support for FF-A MM communication (compatible with EFI boot time)
    - Enabling FF-A and MM communication in Corstone1000 platform as a use case
    - 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.
    - Sandbox FF-A test cases.
    - A new command called armffa is provided as an example of how to access the
      FF-A bus

For more details about the FF-A support please refer to [B] and refer to [C] for
how to use the armffa command.

Please find at [D] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of changes:
===========================

v17:

Ilias:

* show a debug message rather than an error when FF-A is not detected

Tom:

* use savedefconfig to generate corstone1000_defconfig with FF-A MM comms enabled

v16: [16]

Tom:

* lib/efi_loader/Kconfig:
   rather than automatically selecting OPTEE and ARM_FFA_TRANSPORT configs by
   EFI_MM_COMM_TEE, set them as dependencies (Otherwise FF-A will be automatically
   enabled for boards that don't need it).

* configs/corstone1000_defconfig:
   enable MM communication by setting the configs: ARM_FFA_TRANSPORT, OPTEE, TEE

v15: [15]

Simon:

* drop commit "log: select physical address formatting in a generic way",
   this will be sent as a follow-up commit independently from this patchset
* armffa.c : integrate PHYS_ADDR_LN
* replace FFA_SHARED_MM_BUFFER_* defines with configs

v14: [14]

Simon:

    * add to log.h a generic physical address formatting

Ilias:

    * armffa command: in do_ffa_ping() reject the SP ID if it's 0
    * MM comms: drop truncating var_payload->size when using FF-A
    * MM comms: map the MM SP return codes to errnos
    * address nits

v13: [13]

Ilias:
    * remove FF-A and Optee ifdefs in efi_variable_tee.c
    * doc minor change: specify in the readme that the user
       should call ffa_rxtx_unmap() driver operation to unmap
       the RX/TX buffers on demand.

v12: [12]

* remove the global variable (dscvry_info), use uc_priv instead
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* remove reparenting by making the sandbox emulator parent of the FF-A device in the DT
* improve argument checks for the armffa command
* address nits

v11: [11]

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* use U_BOOT_CMD_WITH_SUBCMDS for armffa command
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device
* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* use ut_asserteq_mem() in uuid_str_to_le_bin test case
* address nits

v10: [10]

* provide the FF-A driver operations through the Uclass (arm-ffa-uclass.c)
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c renamed from core.c)
* split the FF-A sandbox support into an emulator (ffa-emul-uclass.c) and a driver (sandbox_ffa.c)
* use the FF-A driver Uclass operations by clients (armffa command, tests, MM comms)
* use uclass_first_device to search and probe the FF-A device (whether it is on Arm or on sandbox)
* address nits

v9: [9]

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
* align FF-A sandbox driver with FF-A discovery through DM
* use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
* add documentation for the armffa command: doc/usage/cmd/armffa.rst
* introduce testcase for uuid_str_to_le_bin

v8: [8]

* pass the FF-A bus device to the bus operations
* isolate the compilation choices between FF-A and OP-TEE
* drop OP-TEE configs from Corstone-1000 defconfig
* make ffa_get_partitions_info() second argument to be an SP count in both
  modes

v7: [7]

* add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v6: [6]

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

List of previous patches:

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
[7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
[8]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
[9]: https://lore.kernel.org/all/20230310141016.137986-1-abdellatif.elkhlifi@arm.com/
[10]: https://lore.kernel.org/all/20230328161157.219375-1-abdellatif.elkhlifi@arm.com/
[11]: https://lore.kernel.org/all/20230412094245.44674-1-abdellatif.elkhlifi@arm.com/
[12]: https://lore.kernel.org/all/20230512121044.111574-1-abdellatif.elkhlifi@arm.com/
[13]: https://lore.kernel.org/all/20230616152817.319869-1-abdellatif.elkhlifi@arm.com/
[14]: https://lore.kernel.org/all/20230707144410.228472-1-abdellatif.elkhlifi@arm.com/
[15]: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/
[16]: https://lore.kernel.org/all/20230726094503.100497-1-abdellatif.elkhlifi@arm.com/

More details:

[A]: https://developer.arm.com/documentation/den0077/latest/
[B]: doc/arch/arm64.ffa.rst
[C]: doc/usage/cmd/armffa.rst
[D]: example of boot logs when enabling FF-A

```
   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64

   DRAM:  2 GiB
   Arm FF-A framework discovery
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   ...
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   EFI: MM partition ID 0x8003
   ...
   EFI stub: Booting Linux Kernel...
   ...
   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
   Machine model: ARM Corstone1000 FPGA MPS3 board
```

Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (10):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce uuid_str_to_le_bin function
  lib: uuid: introduce testcase for uuid_str_to_le_bin
  arm_ffa: introduce Arm FF-A support
  arm_ffa: introduce armffa command
  arm_ffa: introduce sandbox FF-A support
  arm_ffa: introduce sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command Sandbox test
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   18 +
 arch/arm/cpu/armv8/smccc-call.S               |   57 +-
 arch/arm/lib/asm-offsets.c                    |   16 +
 arch/sandbox/dts/sandbox.dtsi                 |    9 +
 arch/sandbox/dts/test.dts                     |    8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |   72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        |  121 ++
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    1 +
 cmd/armffa.c                                  |  202 ++++
 configs/corstone1000_defconfig                |   12 +-
 configs/sandbox64_defconfig                   |    1 +
 configs/sandbox_defconfig                     |    1 +
 doc/arch/arm64.ffa.rst                        |  261 ++++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox/sandbox.rst                  |    1 +
 doc/usage/cmd/armffa.rst                      |   94 ++
 doc/usage/index.rst                           |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   42 +
 drivers/firmware/arm-ffa/Makefile             |   16 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 drivers/firmware/arm-ffa/ffa-emul-uclass.c    |  720 +++++++++++
 drivers/firmware/arm-ffa/sandbox_ffa.c        |  110 ++
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/dm/uclass-id.h                        |    7 +
 include/linux/arm-smccc.h                     |   45 +
 include/mm_communication.h                    |   13 +
 include/uuid.h                                |   15 +
 lib/efi_loader/Kconfig                        |   44 +-
 lib/efi_loader/efi_variable_tee.c             |  257 +++-
 lib/uuid.c                                    |   48 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   33 +
 test/dm/Makefile                              |    3 +-
 test/dm/ffa.c                                 |  261 ++++
 test/lib/Makefile                             |    1 +
 test/lib/uuid.c                               |   41 +
 41 files changed, 4160 insertions(+), 14 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 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 doc/usage/cmd/armffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/lib/uuid.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v17 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-07-27 16:07                                                                                                                                                     ` [PATCH v17 00/10] introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-07-27 16:07                                                                                                                                                       ` Abdellatif El Khlifi
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
                                                                                                                                                                         ` (8 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27 16:07 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, jens.wiklander, nd, sjg, u-boot

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>

---

Changelog:
===============

v9:

* update the copyright string

v7:

* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
 arch/arm/lib/asm-offsets.c      | 16 +++++++++
 include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..93f66d3366 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,7 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
- */
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+*/
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
 #include <generated/asm-offsets.h>
@@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 6de0ce9152..181a8ac4c2 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,11 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * 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>
@@ -90,6 +95,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#ifdef CONFIG_ARM64
+	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..f44e9e8f93 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +74,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v17 02/10] lib: uuid: introduce uuid_str_to_le_bin function
  2023-07-27 16:07                                                                                                                                                     ` [PATCH v17 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-07-27 16:07                                                                                                                                                       ` Abdellatif El Khlifi
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
                                                                                                                                                                         ` (7 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27 16:07 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, jens.wiklander, nd, sjg, u-boot

convert UUID string to little endian binary data

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v9:

* add a full function prototype description in uuid.h

v8:

* use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

include/uuid.h | 15 +++++++++++++++
 lib/uuid.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..89b93e642b 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,10 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +48,15 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ * Return:
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 96e1af3c8b..45f325d964 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * 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>
@@ -354,6 +358,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16;
+	u32 tmp32;
+	u64 tmp64;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+	memcpy(uuid_bin, &tmp32, 4);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16));
+	memcpy(uuid_bin + 10, &tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v17 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-07-27 16:07                                                                                                                                                     ` [PATCH v17 00/10] introduce Arm FF-A support Abdellatif El Khlifi
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2023-07-27 16:07                                                                                                                                                       ` Abdellatif El Khlifi
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                         ` (6 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27 16:07 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, jens.wiklander, nd, sjg, u-boot

provide a test case

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>

---

Changelog:
===============

v16:

* MAINTAINERS: place the UUID part in an alphabetical order

v11:

* use ut_asserteq_mem()

MAINTAINERS       |  5 +++++
 test/lib/Makefile |  1 +
 test/lib/uuid.c   | 41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)
 create mode 100644 test/lib/uuid.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d724b64673..4324965d26 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1555,6 +1555,11 @@ T:	git https://source.denx.de/u-boot/custodians/u-boot-usb.git topic-xhci
 F:	drivers/usb/host/xhci*
 F:	include/usb/xhci.h
 
+UUID testing
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	test/lib/uuid.c
+
 VIDEO
 M:	Anatolij Gustschin <agust@denx.de>
 S:	Maintained
diff --git a/test/lib/Makefile b/test/lib/Makefile
index e0bd9e04e8..e75a263e6a 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_AES) += test_aes.o
 obj-$(CONFIG_GETOPT) += getopt.o
 obj-$(CONFIG_CRC8) += test_crc8.o
 obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o
+obj-$(CONFIG_LIB_UUID) += uuid.o
 else
 obj-$(CONFIG_SANDBOX) += kconfig_spl.o
 endif
diff --git a/test/lib/uuid.c b/test/lib/uuid.c
new file mode 100644
index 0000000000..e24331a136
--- /dev/null
+++ b/test/lib/uuid.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <uuid.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* test UUID */
+#define TEST_SVC_UUID	"ed32d533-4209-99e6-2d72-cdd998a79cc0"
+
+#define UUID_SIZE 16
+
+/* The UUID binary data (little-endian format) */
+static const u8 ref_uuid_bin[UUID_SIZE] = {
+	0x33, 0xd5, 0x32, 0xed,
+	0x09, 0x42, 0xe6, 0x99,
+	0x72, 0x2d, 0xc0, 0x9c,
+	0xa7, 0x98, 0xd9, 0xcd
+};
+
+static int lib_test_uuid_to_le(struct unit_test_state *uts)
+{
+	const char *uuid_str = TEST_SVC_UUID;
+	u8 ret_uuid_bin[UUID_SIZE] = {0};
+
+	ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin));
+	ut_asserteq_mem(ref_uuid_bin, ret_uuid_bin, UUID_SIZE);
+
+	return 0;
+}
+
+LIB_TEST(lib_test_uuid_to_le, 0);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v17 04/10] arm_ffa: introduce Arm FF-A support
  2023-07-27 16:07                                                                                                                                                     ` [PATCH v17 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                         ` (2 preceding siblings ...)
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-07-27 16:07                                                                                                                                                       ` Abdellatif El Khlifi
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                                                                                                                                         ` (5 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27 16:07 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, jens.wiklander, nd, sjg,
	u-boot, Heinrich Schuchardt

Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- ffa_partition_info_get
- ffa_sync_send_receive
- ffa_rxtx_unmap

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 please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v13:

* doc minor change: specify in the readme that the user
   should call ffa_rxtx_unmap() driver operation to unmap
   the RX/TX buffers on demand.

v12:

* remove dscvry_info
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* address nits

v11:

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* pass dev as an argument of arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* add emul field in struct ffa_discovery_info
* address nits

v10:

* provide the driver operations through the Uclass
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c)
* rename core.c to arm-ffa.c
* address nits

v9:

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding

v8:

* make ffa_get_partitions_info() second argument to be an SP count in both
  modes
* update ffa_bus_prvdata_get() to return a pointer rather than a pointer
  address
* remove packing from ffa_partition_info and ffa_send_direct_data structures
* pass the FF-A bus device to the bus operations

v7:

* add support for 32-bit direct messaging
* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* improve the declaration of error handling mapping
* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the U-Boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the U-Boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

MAINTAINERS                                   |    8 +
 doc/arch/arm64.ffa.rst                        |  238 ++++
 doc/arch/index.rst                            |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   36 +
 drivers/firmware/arm-ffa/Makefile             |    8 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |   14 +
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/dm/uclass-id.h                        |    6 +
 13 files changed, 1941 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 4324965d26..4fd5768de0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,6 +266,14 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+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>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..4f817f053c
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,238 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Support
+================
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
+communicate with each other. A partition could be a VM in the Normal or Secure world, an
+application in S-EL0, or a Trusted OS in S-EL1.
+
+The U-Boot FF-A support (the bus) implements the interfaces to communicate
+with partitions in the Secure world aka Secure partitions (SPs).
+
+The FF-A support specifically focuses on communicating with SPs that
+isolate portions of EFI runtime services that must run in a protected
+environment which is inaccessible by the Host OS or Hypervisor.
+Examples of such services are set/get variables.
+
+The FF-A support uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+At this stage of development only EFI boot-time services are supported.
+Runtime support will be added in future developments.
+
+The U-Boot FF-A support provides the following parts:
+
+- A Uclass driver providing generic FF-A methods.
+- An Arm FF-A device driver providing Arm-specific methods and reusing the Uclass methods.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the U-Boot FF-A support relies on
+`FF-A v1.0 specification`_ and uses SMC32 calling convention which
+means using the first 32-bit data of the Xn registers.
+
+At this stage we only need the FF-A v1.0 features.
+
+The FF-A support has been tested with OP-TEE which supports SMC32 calling
+convention.
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A support uses 64-bit registers as per `SMC Calling Convention v1.2 specification`_.
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+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.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers.
+Then, an SMC instruction is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-Boot Arm FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs.
+
+FF-A bus discovery on Arm 64-bit platforms
+---------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
+an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
+This discovery mechanism is performed by the PSCI driver.
+
+The PSCI driver comes with a PSCI device tree node which is the root node for all
+architecture features including FF-A bus.
+
+::
+
+   => dm tree
+
+    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.
+
+In case of FF-A, the callback is arm_ffa_is_supported() which tries to discover the
+FF-A framework by querying the FF-A framework version from secure world using
+FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
+mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver
+with the device using device_bind_driver().
+
+At this stage the FF-A bus is registered with the DM and can be interacted with using
+the DM APIs.
+
+Clients are able to probe then use the FF-A bus by calling uclass_first_device().
+Please refer to the armffa command implementation as an example of how to probe
+and interact with the FF-A bus.
+
+When calling uclass_first_device(), the FF-A driver is probed and ends up calling
+ffa_do_probe() provided by the Uclass which does the following:
+
+    - saving the FF-A framework version in uc_priv
+    - querying from secure world the u-boot endpoint ID
+    - querying from secure world the supported features of FFA_RXTX_MAP
+    - mapping the RX/TX buffers
+    - querying from secure world all the partitions information
+
+When one of the above actions fails, probing fails and the driver stays not active
+and can be probed again if needed.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must query the SPs they are looking for
+during EFI boot-time mode using the service UUID.
+
+The RX/TX buffers are only available at EFI boot-time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped before EFI runtime mode starts.
+The driver provides a bus operation for that called ffa_rxtx_unmap().
+
+The user should call ffa_rxtx_unmap() to unmap the RX/TX buffers when required
+(e.g: at efi_exit_boot_services()).
+
+The Linux kernel allocates its own RX/TX buffers. To be able to register these kernel buffers
+with secure world, the U-Boot's RX/TX buffers should be unmapped before EFI runtime starts.
+
+When invoking FF-A direct messaging, clients should specify which ABI protocol
+they want to use (32-bit vs 64-bit). Selecting the protocol means using
+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
+The calling convention between U-Boot and the secure world stays the same: SMC32.
+
+Requirements for user drivers
+-------------------------------------
+
+Users who want to implement their custom FF-A device driver while reusing the FF-A Uclass can do so
+by implementing their own invoke_ffa_fn() in the user driver.
+
+The bus driver layer
+------------------------------
+
+FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c
+
+The following features are provided:
+
+- Support for the 32-bit version of the following ABIs:
+
+    - FFA_VERSION
+    - FFA_ID_GET
+    - FFA_FEATURES
+    - FFA_PARTITION_INFO_GET
+    - FFA_RXTX_UNMAP
+    - FFA_RX_RELEASE
+    - FFA_RUN
+    - FFA_ERROR
+    - FFA_SUCCESS
+    - FFA_INTERRUPT
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Support for the 64-bit version of the following ABIs:
+
+    - FFA_RXTX_MAP
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, FF-A support takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- FF-A support provides driver operations to be used by upper layers:
+
+    - ffa_partition_info_get
+    - ffa_sync_send_receive
+    - ffa_rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+Example of boot logs with FF-A enabled
+--------------------------------------
+
+For example, when using FF-A with Corstone-1000 the logs are as follows:
+
+::
+
+   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64
+
+   DRAM:  2 GiB
+   Arm FF-A framework discovery
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   ...
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   EFI: MM partition ID 0x8003
+   ...
+   EFI stub: Booting Linux Kernel...
+   ...
+   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
+   Machine model: ARM Corstone1000 FPGA MPS3 board
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+
+.. _`FF-A v1.0 specification`: https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e
+.. _`SMC Calling Convention v1.2 specification`: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index b8da4b8c8e..2f916f4026 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Makefile b/drivers/Makefile
index 78dcf62f76..5044f45253 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -115,6 +115,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index eae1c8ddc9..8789b1ea14 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
 	  the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
 	  services if any and reported as supported by the SMCCC firmware.
 
+source "drivers/firmware/arm-ffa/Kconfig"
 source "drivers/firmware/scmi/Kconfig"
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..9200c8028b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select ARM_SMCCC_FEATURES
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
+	  FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
+	  by the PSCI driver.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  The FF-A support on U-Boot  takes care of all the interactions between Normal
+	  world and Secure World.
+
+	  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
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..11b1766285
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,8 @@
+# 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>
+
+obj-y += arm-ffa-uclass.o arm-ffa.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..ffa9d81fa7
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,1065 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	[NOT_SUPPORTED] = -EOPNOTSUPP,
+	[INVALID_PARAMETERS] = -EINVAL,
+	[NO_MEMORY] = -ENOMEM,
+	[BUSY] = -EBUSY,
+	[INTERRUPTED] = -EINTR,
+	[DENIED] = -EACCES,
+	[RETRY] = -EAGAIN,
+	[ABORTED] = -ECANCELED,
+};
+
+static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			[NO_MEMORY] =
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			[BUSY] =
+			"BUSY: RX buffer of the caller is not free",
+			[DENIED] =
+			"DENIED: Callee is not in a state to handle this request",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			[DENIED] =
+			"DENIED: Caller did not have ownership of the RX buffer",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			[NO_MEMORY] =
+			"NO_MEMORY: Not enough memory",
+			[DENIED] =
+			"DENIED: Buffer pair already registered",
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno() - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+static int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* Map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+static int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* Map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	log_err("%s\n", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/* FF-A ABIs implementation (U-Boot side) */
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void __weak invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+}
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	log_info("FF-A driver %d.%d\nFF-A framework %d.%d\n",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) {
+		log_info("FF-A versions are compatible\n");
+
+		if (dev) {
+			uc_priv = dev_get_uclass_priv(dev);
+			if (uc_priv)
+				uc_priv->fwk_version = res.a0;
+		}
+
+		return 0;
+	}
+
+	log_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id() - FFA_ID_GET handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		uc_priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		log_debug("FF-A endpoint ID is %u\n", uc_priv->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt() - set the minimum number of pages in each of the RX/TX buffers
+ * @dev: The FF-A bus device
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * Set the minimum number of pages in each of the RX/TX buffers in uc_priv
+ *
+ * Return:
+ *
+ * rxtx_min_pages field contains the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	switch (prop_field) {
+	case RXTX_4K:
+		uc_priv->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		uc_priv->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		uc_priv->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		log_err("RX/TX buffer size not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features_hdlr() - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_FEATURES FF-A function to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers() - free the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Free the RX/TX buffers
+ */
+static void ffa_free_rxtx_buffers(struct udevice *dev)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Freeing FF-A RX/TX buffers\n");
+
+	if (uc_priv->pair.rxbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+	}
+
+	if (uc_priv->pair.txbuf) {
+		free(uc_priv->pair.txbuf);
+		uc_priv->pair.txbuf = NULL;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers() - allocate the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ * The size of the memory allocated is the minimum allowed.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(struct udevice *dev)
+{
+	u64 bytes;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Using %lu 4KB page(s) for FF-A RX/TX buffers size\n",
+		  uc_priv->pair.rxtx_min_pages);
+
+	bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 * Assumption: Memory allocated with memalign is always physically contiguous
+	 */
+
+	uc_priv->pair.rxbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.rxbuf) {
+		log_err("failure to allocate RX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A RX buffer at virtual address %p\n", uc_priv->pair.rxbuf);
+
+	uc_priv->pair.txbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.txbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+		log_err("failure to allocate the TX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A TX buffer at virtual address %p\n", uc_priv->pair.txbuf);
+
+	/* Make sure the buffers are cleared before use */
+	memset(uc_priv->pair.rxbuf, 0, bytes);
+	memset(uc_priv->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers_hdlr() - FFA_RXTX_MAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_MAP FF-A function to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	ret = ffa_alloc_rxtx_buffers(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 * no need to convert from virtual to physical
+	 */
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = map_to_sysmem(uc_priv->pair.txbuf),
+			.a2 = map_to_sysmem(uc_priv->pair.rxbuf),
+			.a3 = uc_priv->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		log_debug("FF-A RX/TX buffers mapped\n");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers(dev);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_UNMAP FF-A function to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	log_debug("unmapping FF-A RX/TX buffers\n");
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers(dev);
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer_hdlr() - FFA_RX_RELEASE handler function
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_RX_RELEASE FF-A function to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical() - check whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * Used by ffa_read_partitions_info to search for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+static bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+				   const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info() - read queried partition data
+ * @dev: The FF-A bus device
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * Read the partitions information returned by the FFA_PARTITION_INFO_GET and saves it in uc_priv
+ *
+ * Return:
+ *
+ * uc_priv is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(struct udevice *dev, u32 count,
+				    struct ffa_partition_uuid *part_uuid)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	if (!count) {
+		log_err("no partition detected\n");
+		return -ENODATA;
+	}
+
+	log_debug("Reading FF-A partitions data from the RX buffer\n");
+
+	if (!part_uuid) {
+		/* Querying information of all partitions */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			log_err("partitions data size exceeds the RX buffer size:\n");
+			log_err("    sizes in bytes: data %llu , RX buffer %llu\n",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		uc_priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO);
+		if (!uc_priv->partitions.descs) {
+			log_err("cannot  allocate partitions data buffer\n");
+			return -ENOMEM;
+		}
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			uc_priv->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			log_debug("FF-A partition ID %x : info cached\n",
+				  uc_priv->partitions.descs[desc_idx].info.id);
+		}
+
+		uc_priv->partitions.count = count;
+
+		log_debug("%d FF-A partition(s) found and cached\n", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		/*
+		 * Search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/* Search the current ID in the cached partitions */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < uc_priv->partitions.count;
+			     cached_desc_idx++) {
+				/* Save the UUID */
+				if (uc_priv->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					uc_priv->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info() - invoke FFA_PARTITION_INFO_GET and save partitions data
+ * @dev: The FF-A bus device
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * Execute the FFA_PARTITION_INFO_GET to query the partitions data.
+ * Then, call ffa_read_partitions_info to save the data in uc_priv.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid);
+			if (ret) {
+				log_err("failed reading SP(s) data , err (%d)\n", ret);
+				ffa_release_rx_buffer_hdlr(dev);
+				return -EINVAL;
+			}
+		}
+
+		/* Return the SP count (when querying using a UUID) */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer_hdlr(dev);
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET FF-A function to query the partition information
+ * from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * If the partition(s) matching the UUID found, the partition(s) information and the
+ * number are returned.
+ * If no partition matching the UUID is found in the cached area, a new FFA_PARTITION_INFO_GET
+ * call is issued.
+ * If not done yet, the UUID is updated in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	u32 i;
+	struct ffa_partition_uuid part_uuid = {0};
+	struct ffa_priv *uc_priv;
+	struct ffa_partition_desc *rx_descs;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs) {
+		log_err("no partition installed\n");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		log_err("no UUID provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_count) {
+		log_err("no count argument provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_descs) {
+		log_err("no info argument provided\n");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		log_err("invalid UUID\n");
+		return -EINVAL;
+	}
+
+	log_debug("Searching FF-A partitions using the provided UUID\n");
+
+	*sp_count = 0;
+	*sp_descs = uc_priv->pair.rxbuf;
+	rx_descs = *sp_descs;
+
+	/* Search in the cached partitions */
+	for (i = 0; i < uc_priv->partitions.count; i++)
+		if (ffa_uuid_are_identical(&uc_priv->partitions.descs[i].sp_uuid,
+					   &part_uuid)) {
+			log_debug("FF-A partition ID %x matches the provided UUID\n",
+				  uc_priv->partitions.descs[i].info.id);
+
+			(*sp_count)++;
+			*rx_descs++ = uc_priv->partitions.descs[i];
+			}
+
+	if (!(*sp_count)) {
+		int ret;
+
+		log_debug("No FF-A partition found. Querying framework ...\n");
+
+		ret = ffa_query_partitions_info(dev, &part_uuid, sp_count);
+
+		if (!ret) {
+			log_debug("Number of FF-A partition(s) matching the UUID: %d\n", *sp_count);
+
+			if (*sp_count)
+				ret = ffa_get_partitions_info_hdlr(dev, uuid_str, sp_count,
+								   sp_descs);
+			else
+				ret = -ENODATA;
+		}
+
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info() - Query and saves all secure partitions data
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_PARTITION_INFO_GET FF-A function to query from secure world
+ * all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in uc_priv
+ * and we keep the UUID field empty (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * Called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(struct udevice *dev)
+{
+	return ffa_query_partitions_info(dev, NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Implement FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u64 req_mode, resp_mode;
+	struct ffa_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* No partition installed */
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs)
+		return -ENODEV;
+
+	if (is_smc64) {
+		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+	} else {
+		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = req_mode,
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == resp_mode) {
+		/* Message sent with response extract the return data */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/* FF-A driver operations (used by clients for communicating with FF-A)*/
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Driver operation for FFA_PARTITION_INFO_GET.
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->partition_info_get)
+		return -ENOSYS;
+
+	return ops->partition_info_get(dev, uuid_str, sp_count, sp_descs);
+}
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Driver operation for FFA_MSG_SEND_DIRECT_{REQ,RESP}.
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->sync_send_receive)
+		return -ENOSYS;
+
+	return ops->sync_send_receive(dev, dst_part_id, msg, is_smc64);
+}
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * @dev: The FF-A bus device
+ *
+ * Driver operation for FFA_RXTX_UNMAP.
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_rxtx_unmap(struct udevice *dev)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->rxtx_unmap)
+		return -ENOSYS;
+
+	return ops->rxtx_unmap(dev);
+}
+
+/**
+ * ffa_do_probe() - probing FF-A framework
+ * @dev:	the FF-A bus device (arm_ffa)
+ *
+ * Probing is triggered on demand by clients searching for the uclass.
+ * At probe level the following actions are done:
+ *	- saving the FF-A framework version in uc_priv
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in uc_priv.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_do_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_endpoint_id(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_cache_partitions_info(dev);
+	if (ret) {
+		ffa_unmap_rxtx_buffers_hdlr(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+UCLASS_DRIVER(ffa) = {
+	.name			= "ffa",
+	.id			= UCLASS_FFA,
+	.pre_probe		= ffa_do_probe,
+	.pre_remove		= ffa_unmap_rxtx_buffers_hdlr,
+	.per_device_auto	= sizeof(struct ffa_priv)
+};
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
new file mode 100644
index 0000000000..68df75bd9e
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -0,0 +1,104 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <linux/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * 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 low level SMC assembly function
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * arm_ffa_discover() - perform FF-A discovery
+ * @dev: The Arm FF-A bus device (arm_ffa)
+ * 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:
+ *
+ * true on success. Otherwise, false.
+ */
+static bool arm_ffa_discover(struct udevice *dev)
+{
+	int ret;
+
+	log_info("Arm FF-A framework discovery\n");
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/**
+ * arm_ffa_is_supported() - FF-A bus discovery callback
+ * @invoke_fn: legacy SMC invoke function (not used)
+ *
+ * Perform FF-A discovery by calling arm_ffa_discover().
+ * Discovery is performed by querying the FF-A framework version from
+ * secure world using the FFA_VERSION ABI.
+ *
+ * The FF-A driver is registered as an SMCCC feature driver. So, features discovery
+ * callbacks are called by the PSCI driver (PSCI device is the SMCCC features
+ * root device).
+ *
+ * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
+ * So, the legacy SMC invocation is not used.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static bool arm_ffa_is_supported(void (*invoke_fn)(ulong a0, ulong a1,
+						   ulong a2, ulong a3,
+						   ulong a4, ulong a5,
+						   ulong a6, ulong a7,
+						   struct arm_smccc_res *res))
+{
+	return arm_ffa_discover(NULL);
+}
+
+/* Arm FF-A driver operations */
+
+static const struct ffa_bus_ops 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,
+};
+
+/* Registering the FF-A driver as an SMCCC feature driver */
+
+ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
+	.driver_name = FFA_DRV_NAME,
+	.is_supported = arm_ffa_is_supported,
+};
+
+/* Declaring the FF-A driver under UCLASS_FFA */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.flags		= DM_REMOVE_OS_PREPARE,
+	.ops		= &ffa_ops,
+};
diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
new file mode 100644
index 0000000000..4338f9c9b1
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
@@ -0,0 +1,14 @@
+/* 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/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..db9b1be995
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,213 @@
+/* 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 __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
+ * @a1-4:	32-bit words access to the UUID data
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct ffa_send_direct_data {
+	ulong data0; /* w3/x3 */
+	ulong data1; /* w4/x4 */
+	ulong data2; /* w5/x5 */
+	ulong data3; /* w6/x6 */
+	ulong data4; /* w7/x7 */
+};
+
+struct udevice;
+
+/**
+ * struct ffa_bus_ops - Operations for FF-A
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
+				  u32 *sp_count, struct ffa_partition_desc **sp_descs);
+	int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg,
+				 bool is_smc64);
+	int (*rxtx_unmap)(struct udevice *dev);
+};
+
+#define ffa_get_ops(dev)        ((struct ffa_bus_ops *)(dev)->driver->ops)
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ */
+int ffa_rxtx_unmap(struct udevice *dev);
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The arm_ffa bus device
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev);
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The arm_ffa bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+struct ffa_priv;
+
+/**
+ * ffa_set_smc_conduit() - Set the SMC conduit
+ * @dev: The FF-A bus device
+ *
+ * Selects the SMC conduit by setting the FF-A ABI invoke function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_set_smc_conduit(struct udevice *dev);
+
+#endif
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
new file mode 100644
index 0000000000..d564c33c64
--- /dev/null
+++ b/include/arm_ffa_priv.h
@@ -0,0 +1,246 @@
+/* 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 __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <mapmem.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+
+/* This header is exclusively used by the FF-A Uclass and FF-A driver(s) */
+
+/* Arm FF-A driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* The FF-A SMC function definitions */
+
+#if CONFIG_IS_ENABLED(SANDBOX)
+
+/* Providing Arm SMCCC declarations to sandbox */
+
+/**
+ * struct sandbox_smccc_1_2_regs - emulated SMC call arguments or results
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct sandbox_smccc_1_2_regs {
+	ulong a0;
+	ulong a1;
+	ulong a2;
+	ulong a3;
+	ulong a4;
+	ulong a5;
+	ulong a6;
+	ulong a7;
+	ulong a8;
+	ulong a9;
+	ulong a10;
+	ulong a11;
+	ulong a12;
+	ulong a13;
+	ulong a14;
+	ulong a15;
+	ulong a16;
+	ulong a17;
+};
+
+typedef struct sandbox_smccc_1_2_regs ffa_value_t;
+
+#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))
+
+#else
+/* CONFIG_ARM64 */
+#include <linux/arm-smccc.h>
+typedef struct arm_smccc_1_2_regs ffa_value_t;
+#endif
+
+/* Defining the function pointer type for the function executing the FF-A ABIs */
+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)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR                 = 0x60,
+	FFA_SUCCESS               = 0x61,
+	FFA_INTERRUPT             = 0x62,
+	FFA_VERSION               = 0x63,
+	FFA_FEATURES              = 0x64,
+	FFA_RX_RELEASE            = 0x65,
+	FFA_RXTX_MAP              = 0x66,
+	FFA_RXTX_UNMAP            = 0x67,
+	FFA_PARTITION_INFO_GET    = 0x68,
+	FFA_ID_GET                = 0x69,
+	FFA_RUN                   = 0x6d,
+	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
+	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
+
+	/* To be updated when adding new FFA IDs */
+	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
+	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
+};
+
+enum ffa_abi_errcode {
+	NOT_SUPPORTED = 1,
+	INVALID_PARAMETERS,
+	NO_MEMORY,
+	BUSY,
+	INTERRUPTED,
+	DENIED,
+	RETRY,
+	ABORTED,
+	MAX_NUMBER_FFA_ERR
+};
+
+extern int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR];
+
+/* Container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Hosts the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	void *rxbuf; /* Virtual address returned by memalign */
+	void *txbuf; /* Virtual address returned by memalign */
+	size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */
+};
+
+struct ffa_partition_desc;
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * Contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* Virtual address */
+};
+
+/**
+ * struct ffa_priv - the driver private data structure
+ *
+ * @fwk_version:	FF-A framework version
+ * @emul:	FF-A sandbox emulator
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ *
+ * The device private data structure containing all the
+ * data read from secure world.
+ */
+struct ffa_priv {
+	u32 fwk_version;
+	struct udevice *emul;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+};
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev);
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 307ad6931c..3c6af2e3d2 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,11 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -57,6 +62,7 @@ enum uclass_id {
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_EXTCON,		/* External Connector Class */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v17 05/10] arm_ffa: introduce armffa command
  2023-07-27 16:07                                                                                                                                                     ` [PATCH v17 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                         ` (3 preceding siblings ...)
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-07-27 16:07                                                                                                                                                       ` Abdellatif El Khlifi
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
                                                                                                                                                                         ` (4 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27 16:07 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, jens.wiklander, nd, sjg,
	u-boot, Heinrich Schuchardt

Provide armffa command showcasing the use of the U-Boot FF-A support

armffa is a command showcasing how to invoke FF-A operations.
This provides a guidance to the client developers on how to
call the FF-A bus interfaces. The command also allows to gather secure
partitions information and ping these  partitions. The command is also
helpful in testing the communication with secure partitions.

For more details please refer to the command documentation [1].

[1]: doc/usage/cmd/armffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v15:

Simon:

* armffa.c : integrate PHYS_ADDR_LN

v14:

Ilias:

* address nits
* in do_ffa_ping() reject the SP ID if it's 0
* use PHYS_ADDR_LN in formatting the physical addresses

v12:

* add subcommands argument checks
* usage documentation: update command return codes
* remove calloc when querying SPs
* address nits

v11:

* use U_BOOT_CMD_WITH_SUBCMDS
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* address nits

v9:

* remove manual FF-A discovery and use DM
* use DM class APIs to probe and interact with the FF-A bus
* add doc/usage/cmd/armffa.rst

v8:

* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* adapt do_ffa_dev_list() following the recent update on
  uclass_first_device/uclass_next_device functions (they return void now)
* set armffa command to use 64-bit direct messaging

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

MAINTAINERS                      |   2 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   1 +
 cmd/armffa.c                     | 202 +++++++++++++++++++++++++++++++
 doc/arch/arm64.ffa.rst           |   7 ++
 doc/usage/cmd/armffa.rst         |  94 ++++++++++++++
 doc/usage/index.rst              |   1 +
 drivers/firmware/arm-ffa/Kconfig |   1 +
 8 files changed, 318 insertions(+)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/usage/cmd/armffa.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 4fd5768de0..7bfac78e59 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,7 +269,9 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 S:	Maintained
+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
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 02e54f1e50..79b4f8367a 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -935,6 +935,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the FF-A support
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index 6c37521b4e..7d20a85a46 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,7 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_2048) += 2048.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..7e6eafc03a
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,202 @@
+// 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 <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+#include <asm/io.h>
+
+/* Select the right physical address formatting according to the platform */
+#ifdef CONFIG_PHYS_64BIT
+#define PhysAddrLength "ll"
+#else
+#define PhysAddrLength ""
+#endif
+#define PHYS_ADDR_LN "%" PhysAddrLength "x"
+
+/**
+ * ffa_get_dev() - Return the FF-A device
+ * @devp:	pointer to the FF-A device
+ *
+ * Search for the FF-A device.
+ *
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_dev(struct udevice **devp)
+{
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, devp);
+	if (ret) {
+		log_err("Cannot find FF-A bus device\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * do_ffa_getpart() - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query a secure partition information. The secure partition UUID is provided
+ * as an argument. The function uses the arm_ffa driver
+ * partition_info_get operation which implements FFA_PARTITION_INFO_GET
+ * ABI to retrieve the data. The input UUID string is expected to be in big
+ * endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	u32 i;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+
+	ret = ffa_partition_info_get(dev, argv[1], &count, &descs);
+	if (ret) {
+		log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	/* SPs found , show the partition information */
+	for (i = 0; i < count ; i++) {
+		log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
+			 descs[i].info.id,
+			 descs[i].info.exec_ctxt,
+			 descs[i].info.properties);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_ffa_ping() - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Send data to a secure partition. The secure partition UUID is provided
+ * as an argument. Use the arm_ffa driver sync_send_receive operation
+ * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	part_id = strtoul(argv[1], NULL, 16);
+	if (!part_id) {
+		log_err("Partition ID can not be 0\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	if (!ret) {
+		u8 cnt;
+
+		log_info("SP response:\n[LSB]\n");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			log_info("%llx\n", ((u64 *)&msg)[cnt]);
+		return CMD_RET_SUCCESS;
+	}
+
+	log_err("Sending direct request error (%d)\n", ret);
+	return CMD_RET_FAILURE;
+}
+
+/**
+ *do_ffa_devlist() - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query the device belonging to the UCLASS_FFA
+ * class.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",
+		 dev->name,
+		 map_to_sysmem(dev),
+		 dev->driver->name,
+		 map_to_sysmem(dev->driver->ops));
+
+	return CMD_RET_SUCCESS;
+}
+
+static char armffa_help_text[] =
+	"getpart <partition UUID>\n"
+	"       - lists the partition(s) info\n"
+	"ping <partition ID>\n"
+	"       - sends a data pattern to the specified partition\n"
+	"devlist\n"
+	"       - displays information about the FF-A device/driver\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
+			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
+			U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping),
+			U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist));
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 4f817f053c..aefd527447 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -205,6 +205,13 @@ The following features are provided:
 
 - FF-A bus can be compiled and used without EFI
 
+The armffa command
+-----------------------------------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke the driver operations.
+
+Please refer the command documentation at :doc:`../usage/cmd/armffa`
+
 Example of boot logs with FF-A enabled
 --------------------------------------
 
diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
new file mode 100644
index 0000000000..13fa90c129
--- /dev/null
+++ b/doc/usage/cmd/armffa.rst
@@ -0,0 +1,94 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+
+armffa command
+==============
+
+Synopsis
+--------
+
+::
+
+   armffa [sub-command] [arguments]
+
+   sub-commands:
+
+        getpart [partition UUID]
+
+            lists the partition(s) info
+
+        ping [partition ID]
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays information about the FF-A device/driver
+
+Description
+-----------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
+
+The command also allows to gather secure partitions information and ping these  partitions.
+
+The command is also helpful in testing the communication with secure partitions.
+
+Example
+-------
+
+The following examples are run on Corstone-1000 platform.
+
+* ping
+
+::
+
+   corstone1000# armffa ping 0x8003
+   SP response:
+   [LSB]
+   fffffffe
+   0
+   0
+   0
+   0
+
+* ping (failure case)
+
+::
+
+   corstone1000# armffa ping 0
+   Sending direct request error (-22)
+
+* getpart
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
+   Partition: id = 8003 , exec_ctxt 1 , properties 3
+
+* getpart (failure case)
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221
+   INVALID_PARAMETERS: Unrecognized UUID
+   Failure in querying partitions count (error code: -22)
+
+* devlist
+
+::
+
+   corstone1000# armffa devlist
+   device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98
+
+Configuration
+-------------
+
+The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
+
+Return value
+------------
+
+The return value $? is 0 (true) on success, 1 (false) on failure.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 388e59f173..e462de2806 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -22,6 +22,7 @@ Shell commands
 
    cmd/acpi
    cmd/addrmap
+   cmd/armffa
    cmd/askenv
    cmd/base
    cmd/bdinfo
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index 9200c8028b..a7d5392859 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
 	depends on DM && ARM64
 	select ARM_SMCCC
 	select ARM_SMCCC_FEATURES
+	imply CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v17 06/10] arm_ffa: introduce sandbox FF-A support
  2023-07-27 16:07                                                                                                                                                     ` [PATCH v17 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                         ` (4 preceding siblings ...)
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-07-27 16:07                                                                                                                                                       ` Abdellatif El Khlifi
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                                                                                                                                         ` (3 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27 16:07 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, jens.wiklander, nd, sjg,
	u-boot, Heinrich Schuchardt

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>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove reparenting by making the emulator parent of the FF-A device in the DT
* add invoke_ffa_fn()
* address nits

v11:

* rename ffa_try_discovery() to sandbox_ffa_discover()
* rename sandbox_ffa_query_core_state() to sandbox_query_ffa_emul_state()
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device

v10:

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

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

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

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

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

v1: introduce the sandbox driver

MAINTAINERS                                   |   3 +-
 arch/sandbox/dts/sandbox.dtsi                 |   9 +
 arch/sandbox/dts/test.dts                     |   8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |  72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        | 121 +++
 configs/sandbox64_defconfig                   |   1 +
 configs/sandbox_defconfig                     |   1 +
 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, 1081 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 7bfac78e59..7f4efb6358 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..96b5404991 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1820,6 +1820,14 @@
 	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..72ea3d21ab 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -260,3 +260,4 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 1ec44d5b33..8269bec879 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -344,3 +344,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 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


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v17 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA
  2023-07-27 16:07                                                                                                                                                     ` [PATCH v17 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                         ` (5 preceding siblings ...)
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
@ 2023-07-27 16:07                                                                                                                                                       ` Abdellatif El Khlifi
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
                                                                                                                                                                         ` (2 subsequent siblings)
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27 16:07 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, jens.wiklander, nd, sjg,
	u-boot, Heinrich Schuchardt

Add functional test cases for the FF-A support

These tests rely on the FF-A sandbox emulator and FF-A
sandbox driver which help in inspecting the FF-A communication.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove use of dscvry_info
* drop use of calloc when querying SPs
* address nits

v11:

* drop unmapping test (taken care of by the DM when removing the device)
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT
* address nits

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

v8:

  * update partition_info_get() second argument to be an SP count
  * pass NULL device pointer to the FF-A bus discovery and operations

v7: set the tests to use 64-bit direct messaging

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

v1: introduce sandbox tests

MAINTAINERS            |   1 +
 doc/arch/arm64.ffa.rst |   1 +
 test/dm/Makefile       |   3 +-
 test/dm/ffa.c          | 261 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 265 insertions(+), 1 deletion(-)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7f4efb6358..a79e3a8429 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index b7c754fa3d..325fb80346 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -37,6 +37,7 @@ The U-Boot FF-A support provides the following parts:
   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.
+- Sandbox FF-A test cases.
 
 FF-A and SMC specifications
 -------------------------------------------
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 3799b1ae8f..7ed00733c1 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
-# Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -92,6 +92,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..6912666bb4
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <console.h>
+#include <dm.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <asm/sandbox_arm_ffa_priv.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Functional tests for the UCLASS_FFA */
+
+static int check_fwk_version(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	struct ffa_sandbox_data func_data;
+	u32 fwk_version = 0;
+
+	func_data.data0 = &fwk_version;
+	func_data.data0_size = sizeof(fwk_version);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_VERSION, &func_data));
+	ut_asserteq(uc_priv->fwk_version, fwk_version);
+
+	return 0;
+}
+
+static int check_endpoint_id(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_asserteq(0, uc_priv->id);
+
+	return 0;
+}
+
+static int check_rxtxbuf(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assertnonnull(uc_priv->pair.rxbuf);
+	ut_assertnonnull(uc_priv->pair.txbuf);
+
+	return 0;
+}
+
+static int check_features(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assert(uc_priv->pair.rxtx_min_pages == RXTX_4K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_16K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_64K);
+
+	return 0;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+		ut_asserteq(1, rxbuf_mapped);
+		break;
+	case FFA_RXTX_UNMAP:
+		ut_asserteq(0, rxbuf_mapped);
+		break;
+	default:
+		ut_assert(false);
+	}
+
+	return 0;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	ut_asserteq(0, rxbuf_owned);
+
+	return 0;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg;
+	u8 cnt;
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]);
+
+	return 0;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct unit_test_state *uts)
+{
+	struct ffa_partition_desc *descs;
+	u32 count, i, j, valid_sps = 0;
+	struct udevice *dev;
+	struct ffa_sandbox_data func_data;
+	struct ffa_partitions *partitions;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get from the driver the count and information of the SPs matching the UUID */
+	ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, &descs));
+
+	/* Make sure the count is correct */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+
+	/* SPs found , verify the partitions information */
+
+	func_data.data0 = &partitions;
+	func_data.data0_size = sizeof(struct ffa_partitions *);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_PARTITION_INFO_GET, &func_data));
+
+	for (i = 0; i < count ; i++) {
+		for (j = 0;
+		     j < partitions->count;
+		     j++) {
+			if (descs[i].info.id ==
+			   partitions->descs[j].info.id) {
+				valid_sps++;
+				ut_asserteq_mem(&descs[i],
+						&partitions->descs[j],
+						sizeof(struct ffa_partition_desc));
+				/* Send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(descs[i].info.id, uts);
+			}
+		}
+	}
+
+	/* Verify expected partitions found in the emulated secure world */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, valid_sps);
+
+	return 0;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	struct ffa_sandbox_data func_data;
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	struct udevice *dev;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Test FFA_VERSION */
+	check_fwk_version(uc_priv, uts);
+
+	/* Test FFA_ID_GET */
+	check_endpoint_id(uc_priv, uts);
+
+	/* Test FFA_FEATURES */
+	check_features(uc_priv, uts);
+
+	/*  Test RX/TX buffers */
+	check_rxtxbuf(uc_priv, uts);
+
+	/* Test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	sandbox_query_ffa_emul_state(FFA_RXTX_MAP, &func_data);
+	check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc1_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data);
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc2_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data));
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg;
+	int ret;
+	u32 count;
+	u16 part_id = 0;
+	struct udevice *dev;
+	struct ffa_partition_desc *descs = NULL;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Query partitions count using  invalid arguments */
+	ret = ffa_partition_info_get(dev, NULL, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, NULL);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID  string */
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid_str, &count, &descs);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, &descs);
+	ut_asserteq(0, count);
+
+	/* Query partitions data using a valid UUID */
+	count = 0;
+	ut_assertok(ffa_partition_info_get(dev, valid_svc_uuid, &count, &descs));
+	/* Make sure partitions are detected */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+	ut_assertnonnull(descs);
+
+	/* Send data to an invalid partition */
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Send data to a valid partition */
+	part_id = uc_priv->partitions.descs[0].info.id;
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v17 08/10] arm_ffa: introduce armffa command Sandbox test
  2023-07-27 16:07                                                                                                                                                     ` [PATCH v17 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                         ` (6 preceding siblings ...)
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-07-27 16:07                                                                                                                                                       ` Abdellatif El Khlifi
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27 16:07 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, jens.wiklander, nd, sjg, u-boot

Add Sandbox test for the armffa command

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v12:

* address nits

v10:

* replace CMD_RET_SUCCESS with 0
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT

v9: align the test with FF-A discovery through DM

v4: drop use of helper APIs

v1: introduce armffa command sandbox test

MAINTAINERS       |  1 +
 test/cmd/Makefile |  2 ++
 test/cmd/armffa.c | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+)
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a79e3a8429..bd3dba3d95 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -276,6 +276,7 @@ F:	doc/arch/arm64.ffa.rst
 F:	doc/usage/cmd/armffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index a3cf983739..6e3d7e919e 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -24,6 +25,7 @@ obj-$(CONFIG_CMD_SEAMA) += seama.o
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_CMD_READ) += rw.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o
 endif
 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
 obj-$(CONFIG_CMD_WGET) += wget.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..9a44a397e8
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * 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 <string.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	/* armffa ping <ID> */
+	ut_assertok(run_commandf("armffa ping 0x%x", SANDBOX_SP1_ID));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return 0;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-27 16:07                                                                                                                                                     ` [PATCH v17 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                         ` (7 preceding siblings ...)
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
@ 2023-07-27 16:07                                                                                                                                                       ` Abdellatif El Khlifi
  2023-07-27 16:43                                                                                                                                                         ` Tom Rini
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  9 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27 16:07 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, jens.wiklander, nd, sjg,
	u-boot, Gowtham Suresh Kumar

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

MM communication protocol supports FF-A 64-bit direct messaging.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v17:

* show a debug message rather than an error when FF-A is not detected

v16:

* lib/efi_loader/Kconfig:
   rather than automatically selecting OPTEE and ARM_FFA_TRANSPORT configs by
   EFI_MM_COMM_TEE, set them as dependencies (Otherwise FF-A will be automatically
   enabled for boards that don't need it).

v15:

Simon:

* replace FFA_SHARED_MM_BUFFER_* defines with configs

v14:

Ilias:

* drop truncating var_payload->size when using FF-A
* map the MM SP return codes to errnos

v13:

* remove FF-A and Optee ifdefs

v12:

* drop use of calloc when querying SPs
* address nits

v11:

* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* addressing nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* addressing nits

v9: align how FF-A is used with FF-A discovery through DM

v8:

* isolate the compilation choices between FF-A and OP-TEE
* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make mm_sp_svc_uuid static
* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
* improve use of unmap_sysmem() in ffa_mm_communicate()

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

include/mm_communication.h        |  13 ++
 lib/efi_loader/Kconfig            |  44 ++++-
 lib/efi_loader/efi_variable_tee.c | 257 +++++++++++++++++++++++++++++-
 3 files changed, 307 insertions(+), 7 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..f17847583b 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,9 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *    Authors:
+ *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +16,9 @@
 
 #include <part_efi.h>
 
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
@@ -248,4 +254,11 @@ struct smm_variable_var_check_property {
 	u16                       name[];
 };
 
+/* supported MM transports */
+enum mm_comms_select {
+	MM_COMMS_UNDEFINED,
+	MM_COMMS_FFA,
+	MM_COMMS_OPTEE
+};
+
 #endif /* _MM_COMMUNICATION_H_ */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c5835e6ef6..8fbadb9201 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
-	depends on OPTEE
+	bool "UEFI variables storage service via the trusted world"
+	depends on OPTEE && ARM_FFA_TRANSPORT
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
+config FFA_SHARED_MM_BUF_SIZE
+	int "Memory size of the shared MM communication buffer"
+	default 0
+	depends on EFI_MM_COMM_TEE
+	help
+	  This defines the size in bytes of the memory area reserved for the shared
+	  buffer used for communication between the MM feature in U-Boot and
+	  the MM SP in secure world.
+	  The size of the memory region must be a multiple of the size of the maximum
+	  translation granule size that is specified in the ID_AA64MMFR0_EL1 System register.
+	  It is assumed that the MM SP knows the size of the shared MM communication buffer.
+
+config FFA_SHARED_MM_BUF_OFFSET
+	int "Data offset in the shared MM communication buffer"
+	default 0
+	depends on EFI_MM_COMM_TEE
+	help
+	  This defines the offset in bytes of the data read or written to in the shared
+	  buffer by the MM SP.
+
+config FFA_SHARED_MM_BUF_ADDR
+	hex "Define the address of the shared MM communication buffer"
+	default 0x0
+	depends on EFI_MM_COMM_TEE
+	help
+	  This defines the address of the shared MM communication buffer
+	  used for communication between the MM feature in U-Boot and
+	  the MM SP in secure world.
+	  It is assumed that the MM SP knows the address of the shared MM communication buffer.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..3064a88ffe 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,17 +4,34 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  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 <cpu_func.h>
+#include <dm.h>
 #include <efi.h>
 #include <efi_api.h>
 #include <efi_loader.h>
 #include <efi_variable.h>
-#include <tee.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <mm_communication.h>
+#include <tee.h>
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+#define MM_NOT_SUPPORTED (-1)
+#define MM_INVALID_PARAMETER (-2)
+#define MM_DENIED (-3)
+#define MM_NO_MEMORY (-5)
 
+static const char *mm_sp_svc_uuid = MM_SP_UUID;
+static u16 mm_sp_id;
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
 static efi_uintn_t max_payload_size;	/* func + data */
@@ -145,16 +162,241 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 }
 
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notify the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
+		return ret;
+	}
+
+	msg.data0 = CONFIG_FFA_SHARED_MM_BUF_OFFSET; /* x3 */
+
+	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
+	if (ret)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	switch (sp_event_ret) {
+	case MM_SUCCESS:
+		ret = 0;
+		break;
+	case MM_NOT_SUPPORTED:
+		ret = -EINVAL;
+		break;
+	case MM_INVALID_PARAMETER:
+		ret = -EPERM;
+		break;
+	case MM_DENIED:
+		ret = -EACCES;
+		break;
+	case MM_NO_MEMORY:
+		ret = -EBUSY;
+		break;
+	default:
+		ret = -EACCES;
+	}
+
+	return ret;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
+		return ret;
+	}
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, &descs);
+	if (ret) {
+		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
+		return ret;
+	}
+
+	/* MM SPs found , use the first one */
+
+	mm_sp_id = descs[0].info.id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	return 0;
+}
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	efi_status_t efi_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()) {
+		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > CONFIG_FFA_SHARED_MM_BUF_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = map_sysmem((phys_addr_t)CONFIG_FFA_SHARED_MM_BUF_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+
+	switch (ffa_ret) {
+	case 0: {
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		efi_ret = EFI_SUCCESS;
+		break;
+	}
+	case -EINVAL:
+		efi_ret = EFI_DEVICE_ERROR;
+		break;
+	case -EPERM:
+		efi_ret = EFI_INVALID_PARAMETER;
+		break;
+	case -EACCES:
+		efi_ret = EFI_ACCESS_DENIED;
+		break;
+	case -EBUSY:
+		efi_ret = EFI_OUT_OF_RESOURCES;
+		break;
+	default:
+		efi_ret = EFI_ACCESS_DENIED;
+	}
+
+	unmap_sysmem(virt_shared_buf);
+	return efi_ret;
+}
+
+/**
+ * get_mm_comms() - detect the available MM transport
+ *
+ * Make sure the FF-A bus is probed successfully
+ * which means FF-A communication with secure world works and ready
+ * for use.
+ *
+ * If FF-A bus is not ready, use OPTEE comms.
+ *
+ * Return:
+ *
+ * MM_COMMS_FFA or MM_COMMS_OPTEE
+ */
+static enum mm_comms_select get_mm_comms(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_debug("EFI: Cannot find FF-A bus device, trying Optee comms\n");
+		return MM_COMMS_OPTEE;
+	}
+
+	return MM_COMMS_FFA;
+}
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 {
 	efi_status_t ret;
+	enum mm_comms_select mm_comms;
 	struct efi_mm_communicate_header *mm_hdr;
 	struct smm_variable_communicate_header *var_hdr;
 
@@ -162,7 +404,12 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+	mm_comms = get_mm_comms();
+	if (mm_comms == MM_COMMS_FFA)
+		ret = ffa_mm_communicate(comm_buf, dsize);
+	else
+		ret = optee_mm_communicate(comm_buf, dsize);
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -697,7 +944,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v17 10/10] arm_ffa: efi: corstone1000: enable MM communication
  2023-07-27 16:07                                                                                                                                                     ` [PATCH v17 00/10] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                         ` (8 preceding siblings ...)
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-07-27 16:07                                                                                                                                                       ` Abdellatif El Khlifi
  9 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-27 16:07 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, ilias.apalodimas, jens.wiklander, nd, sjg, u-boot

turn on EFI MM communication

On Corstone-1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

Changes made are generated using savedefconfig.

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>

---

Changelog:
===============

v17:

* use savedefconfig to generate corstone1000_defconfig with FF-A MM comms enabled

v16:

* configs/corstone1000_defconfig:
   enable MM communication by setting the configs: ARM_FFA_TRANSPORT, OPTEE, TEE

v15:

Simon:

* use CONFIG_FFA_SHARED_MM_BUF_* configs in place of FFA_SHARED_MM_BUFFER_*

v13:

* remove FF-A config in the defconfig
   (because it's enabled automatically by CONFIG_EFI_MM_COMM_TEE)

v9:

* update copyright string

v8:

* drop OP-TEE configs from Corstone-1000 defconfig

v7:

* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
  FFA_SHARED_MM_BUFFER_OFFSET
* update FFA_SHARED_MM_BUFFER_ADDR value

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

configs/corstone1000_defconfig | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index a8a79fd105..67684e114d 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -28,12 +28,10 @@ CONFIG_CMD_FWU_METADATA=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_SYS_BOOTM_LEN=0x800000
 # CONFIG_CMD_XIMG is not set
-CONFIG_CMD_NVMXIP=y
 CONFIG_CMD_GPT=y
 # CONFIG_RANDOM_UUID is not set
 CONFIG_CMD_LOADM=y
 # CONFIG_CMD_LOADS is not set
-CONFIG_CMD_MMC=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NFS is not set
@@ -45,8 +43,7 @@ CONFIG_OF_CONTROL=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_REGMAP=y
-CONFIG_FWU_MDATA=y
-CONFIG_FWU_MDATA_GPT_BLK=y
+CONFIG_ARM_FFA_TRANSPORT=y
 CONFIG_MISC=y
 # CONFIG_MMC is not set
 CONFIG_NVMXIP_QSPI=y
@@ -59,9 +56,14 @@ CONFIG_DM_RTC=y
 CONFIG_RTC_EMULATION=y
 CONFIG_DM_SERIAL=y
 CONFIG_SYSRESET=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760=y
+CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
+CONFIG_FFA_SHARED_MM_BUF_SIZE=4096
+CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000
 CONFIG_EFI_CAPSULE_ON_DISK=y
 CONFIG_EFI_IGNORE_OSINDICATIONS=y
 CONFIG_FWU_MULTI_BANK_UPDATE=y
-CONFIG_ERRNO_STR=y
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-07-27 16:43                                                                                                                                                         ` Tom Rini
  2023-07-28  9:37                                                                                                                                                           ` Abdellatif El Khlifi
  2023-07-28 11:00                                                                                                                                                           ` Ilias Apalodimas
  0 siblings, 2 replies; 478+ messages in thread
From: Tom Rini @ 2023-07-27 16:43 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: ilias.apalodimas, jens.wiklander, nd, sjg, u-boot, Gowtham Suresh Kumar

[-- Attachment #1: Type: text/plain, Size: 2279 bytes --]

On Thu, Jul 27, 2023 at 05:07:11PM +0100, Abdellatif El Khlifi wrote:

> Add MM communication support using FF-A transport
> 
> This feature allows accessing MM partitions services through
> EFI MM communication protocol. MM partitions such as StandAlonneMM
> or smm-gateway secure partitions which reside in secure world.
> 
> An MM shared buffer and a door bell event are used to exchange
> the data.
> 
> The data is used by EFI services such as GetVariable()/SetVariable()
> and copied from the communication buffer to the MM shared buffer.
> 
> The secure partition is notified about availability of data in the
> MM shared buffer by an FF-A message (door bell).
> 
> On such event, MM SP can read the data and updates the MM shared
> buffer with the response data.
> 
> The response data is copied back to the communication buffer and
> consumed by the EFI subsystem.
> 
> MM communication protocol supports FF-A 64-bit direct messaging.
> 
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Cc: Jens Wiklander <jens.wiklander@linaro.org>
> 
> ---
> 
> Changelog:
> ===============
> 
> v17:
> 
> * show a debug message rather than an error when FF-A is not detected
[snip]
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index c5835e6ef6..8fbadb9201 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
>  	  stored as file /ubootefi.var on the EFI system partition.
>  
>  config EFI_MM_COMM_TEE
> -	bool "UEFI variables storage service via OP-TEE"
> -	depends on OPTEE
> +	bool "UEFI variables storage service via the trusted world"
> +	depends on OPTEE && ARM_FFA_TRANSPORT

You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
you don't make this option depend on EFI_MM_COMM_TEE.  If FF-A is only
for use here, you make FF-A depend on this, and the FF-A specific
variable depend on ARM_FFA_TRANSPORT.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 2/6] arm_ffa: introduce armffa command
  2023-07-27  9:00     ` Abdellatif El Khlifi
@ 2023-07-28  1:52       ` Simon Glass
  2023-07-28  9:53         ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-07-28  1:52 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: Heinrich Schuchardt, nd, u-boot

Hi Abdellatif,

On Thu, 27 Jul 2023 at 03:00, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Hi Heinrich,
>
> On Thu, Jul 27, 2023 at 07:51:42AM +0200, Heinrich Schuchardt wrote:
> > On 3/29/22 17:16, abdellatif.elkhlifi@arm.com wrote:
> > > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > >
> > > Provide armffa command showcasing the use of the FF-A driver
> > >
> > > The armffa command allows to query secure partitions data from
> > > the secure world and exchanging messages with the partitions.
> > >
> > > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > Cc: Tom Rini <trini@konsulko.com>
> > > ---
> > >   MAINTAINERS             |   1 +
> > >   cmd/Kconfig             |  10 ++
> > >   cmd/Makefile            |   2 +
> > >   cmd/armffa.c            | 266 ++++++++++++++++++++++++++++++++++++++++
> > >   drivers/arm-ffa/Kconfig |   1 +
> >
> > We want to have all commands to be documented in /doc/usage/cmd/.
> >
> > Could you, please, provide the missing /doc/usage/cmd/armffa.rst file.
> >
>
> It's here [1].

I'd suggest mentioning that in the commit message for this patch, or
even putting the testin the same patch, along with the test for the
command. I find it hard to keep track of this too.

>
> [1]: https://lore.kernel.org/all/20230726094503.100497-6-abdellatif.elkhlifi@arm.com/#Z31doc:usage:cmd:armffa.rst
>
> Cheers,
> Abdellatif

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-27 16:43                                                                                                                                                         ` Tom Rini
@ 2023-07-28  9:37                                                                                                                                                           ` Abdellatif El Khlifi
  2023-07-28 11:00                                                                                                                                                           ` Ilias Apalodimas
  1 sibling, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-28  9:37 UTC (permalink / raw)
  To: Tom Rini; +Cc: nd, u-boot, ilias.apalodimas

Hi Tom,

On Thu, Jul 27, 2023 at 12:43:45PM -0400, Tom Rini wrote:
> On Thu, Jul 27, 2023 at 05:07:11PM +0100, Abdellatif El Khlifi wrote:
> 
> > Add MM communication support using FF-A transport
> > 
> > This feature allows accessing MM partitions services through
> > EFI MM communication protocol. MM partitions such as StandAlonneMM
> > or smm-gateway secure partitions which reside in secure world.
> > 
> > An MM shared buffer and a door bell event are used to exchange
> > the data.
> > 
> > The data is used by EFI services such as GetVariable()/SetVariable()
> > and copied from the communication buffer to the MM shared buffer.
> > 
> > The secure partition is notified about availability of data in the
> > MM shared buffer by an FF-A message (door bell).
> > 
> > On such event, MM SP can read the data and updates the MM shared
> > buffer with the response data.
> > 
> > The response data is copied back to the communication buffer and
> > consumed by the EFI subsystem.
> > 
> > MM communication protocol supports FF-A 64-bit direct messaging.
> > 
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> > Cc: Tom Rini <trini@konsulko.com>
> > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > Cc: Jens Wiklander <jens.wiklander@linaro.org>
> > 
> > ---
> > 
> > Changelog:
> > ===============
> > 
> > v17:
> > 
> > * show a debug message rather than an error when FF-A is not detected
> [snip]
> > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > index c5835e6ef6..8fbadb9201 100644
> > --- a/lib/efi_loader/Kconfig
> > +++ b/lib/efi_loader/Kconfig
> > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> >  	  stored as file /ubootefi.var on the EFI system partition.
> >  
> >  config EFI_MM_COMM_TEE
> > -	bool "UEFI variables storage service via OP-TEE"
> > -	depends on OPTEE
> > +	bool "UEFI variables storage service via the trusted world"
> > +	depends on OPTEE && ARM_FFA_TRANSPORT
> 
> You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> you don't make this option depend on EFI_MM_COMM_TEE.  If FF-A is only
> for use here, you make FF-A depend on this, and the FF-A specific
> variable depend on ARM_FFA_TRANSPORT.

Thanks for the suggestion.

EFI_MM_COMM_TEE needs ARM_FFA_TRANSPORT.

EFI_MM_COMM_TEE enables  efi_variable_tee.c

efi_variable_tee.c has new code  for FF-A and Optee. Detecting which method to use
is done at runtime. Ilias and I agreed on that.

ARM_FFA_TRANSPORT is meant to be generic and not tied to EFI.
Making it depends on EFI_MM_COMM_TEE will tie it to EFI. 

Cheers
Abdellatif

> 
> -- 
> Tom



^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH 2/6] arm_ffa: introduce armffa command
  2023-07-28  1:52       ` Simon Glass
@ 2023-07-28  9:53         ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-28  9:53 UTC (permalink / raw)
  To: Simon Glass; +Cc: xypron.glpk, nd, u-boot

Hi Simon, Heinrich,

On Thu, Jul 27, 2023 at 07:52:00PM -0600, Simon Glass wrote:
> Hi Abdellatif,
> 
> On Thu, 27 Jul 2023 at 03:00, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > Hi Heinrich,
> >
> > On Thu, Jul 27, 2023 at 07:51:42AM +0200, Heinrich Schuchardt wrote:
> > > On 3/29/22 17:16, abdellatif.elkhlifi@arm.com wrote:
> > > > From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > >
> > > > Provide armffa command showcasing the use of the FF-A driver
> > > >
> > > > The armffa command allows to query secure partitions data from
> > > > the secure world and exchanging messages with the partitions.
> > > >
> > > > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > Cc: Tom Rini <trini@konsulko.com>
> > > > ---
> > > >   MAINTAINERS             |   1 +
> > > >   cmd/Kconfig             |  10 ++
> > > >   cmd/Makefile            |   2 +
> > > >   cmd/armffa.c            | 266 ++++++++++++++++++++++++++++++++++++++++
> > > >   drivers/arm-ffa/Kconfig |   1 +
> > >
> > > We want to have all commands to be documented in /doc/usage/cmd/.
> > >
> > > Could you, please, provide the missing /doc/usage/cmd/armffa.rst file.
> > >
> >
> > It's here [1].
> 
> I'd suggest mentioning that in the commit message for this patch, or
> even putting the testin the same patch, along with the test for the
> command. I find it hard to keep track of this too.

Please refer to the commit provided by the latest version (v17).

In the commit message the path to doc/usage/cmd/armffa.rst is already given.

Please refer to the commit [A].

The commit log says: For more details please refer to the command documentation [1].

[A]: https://lore.kernel.org/all/20230727160712.81477-6-abdellatif.elkhlifi@arm.com/

Cheers
Abdellatif

> 
> >
> > [1]: https://lore.kernel.org/all/20230726094503.100497-6-abdellatif.elkhlifi@arm.com/#Z31doc:usage:cmd:armffa.rst
> >
> > Cheers,
> > Abdellatif
> 
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-27 16:43                                                                                                                                                         ` Tom Rini
  2023-07-28  9:37                                                                                                                                                           ` Abdellatif El Khlifi
@ 2023-07-28 11:00                                                                                                                                                           ` Ilias Apalodimas
  2023-07-28 13:54                                                                                                                                                             ` Tom Rini
  1 sibling, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-07-28 11:00 UTC (permalink / raw)
  To: Tom Rini
  Cc: Abdellatif El Khlifi, jens.wiklander, nd, sjg, u-boot,
	Gowtham Suresh Kumar

Hi Tom

On Thu, 27 Jul 2023 at 19:43, Tom Rini <trini@konsulko.com> wrote:
>
> On Thu, Jul 27, 2023 at 05:07:11PM +0100, Abdellatif El Khlifi wrote:
>
> > Add MM communication support using FF-A transport
> >
> > This feature allows accessing MM partitions services through
> > EFI MM communication protocol. MM partitions such as StandAlonneMM
> > or smm-gateway secure partitions which reside in secure world.
> >
> > An MM shared buffer and a door bell event are used to exchange
> > the data.
> >
> > The data is used by EFI services such as GetVariable()/SetVariable()
> > and copied from the communication buffer to the MM shared buffer.
> >
> > The secure partition is notified about availability of data in the
> > MM shared buffer by an FF-A message (door bell).
> >
> > On such event, MM SP can read the data and updates the MM shared
> > buffer with the response data.
> >
> > The response data is copied back to the communication buffer and
> > consumed by the EFI subsystem.
> >
> > MM communication protocol supports FF-A 64-bit direct messaging.
> >
> > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> > Cc: Tom Rini <trini@konsulko.com>
> > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > Cc: Jens Wiklander <jens.wiklander@linaro.org>
> >
> > ---
> >
> > Changelog:
> > ===============
> >
> > v17:
> >
> > * show a debug message rather than an error when FF-A is not detected
> [snip]
> > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > index c5835e6ef6..8fbadb9201 100644
> > --- a/lib/efi_loader/Kconfig
> > +++ b/lib/efi_loader/Kconfig
> > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> >         stored as file /ubootefi.var on the EFI system partition.
> >
> >  config EFI_MM_COMM_TEE
> > -     bool "UEFI variables storage service via OP-TEE"
> > -     depends on OPTEE
> > +     bool "UEFI variables storage service via the trusted world"
> > +     depends on OPTEE && ARM_FFA_TRANSPORT
>
> You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> you don't make this option depend on .  If FF-A is only
> for use here, you make FF-A depend on this, and the FF-A specific
> variable depend on ARM_FFA_TRANSPORT.

Abdellatif hinted at what's going on here.  When I added this Kconfig
option to lx2160 FF-A wasn't implemented yet.  Since FF-A isn't a new
communication mechanism but builds upon the existing SMCs to build an
easier API, I asked Abdellatif to hide this complexity.
We had two options, either make Kconfig options for either FF-A or the
traditional SMCs and remove the dependencies,  or piggyback on FF-As
discovery mechanism and make the choice at runtime.  The latter has a
small impact on code size, but imho makes developers' life a lot
easier.

Thanks
/Ilias

>
> --
> Tom

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-28 11:00                                                                                                                                                           ` Ilias Apalodimas
@ 2023-07-28 13:54                                                                                                                                                             ` Tom Rini
  2023-07-31  9:38                                                                                                                                                               ` Ilias Apalodimas
  0 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-07-28 13:54 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Abdellatif El Khlifi, jens.wiklander, nd, sjg, u-boot,
	Gowtham Suresh Kumar

[-- Attachment #1: Type: text/plain, Size: 3835 bytes --]

On Fri, Jul 28, 2023 at 02:00:25PM +0300, Ilias Apalodimas wrote:
> Hi Tom
> 
> On Thu, 27 Jul 2023 at 19:43, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Thu, Jul 27, 2023 at 05:07:11PM +0100, Abdellatif El Khlifi wrote:
> >
> > > Add MM communication support using FF-A transport
> > >
> > > This feature allows accessing MM partitions services through
> > > EFI MM communication protocol. MM partitions such as StandAlonneMM
> > > or smm-gateway secure partitions which reside in secure world.
> > >
> > > An MM shared buffer and a door bell event are used to exchange
> > > the data.
> > >
> > > The data is used by EFI services such as GetVariable()/SetVariable()
> > > and copied from the communication buffer to the MM shared buffer.
> > >
> > > The secure partition is notified about availability of data in the
> > > MM shared buffer by an FF-A message (door bell).
> > >
> > > On such event, MM SP can read the data and updates the MM shared
> > > buffer with the response data.
> > >
> > > The response data is copied back to the communication buffer and
> > > consumed by the EFI subsystem.
> > >
> > > MM communication protocol supports FF-A 64-bit direct messaging.
> > >
> > > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
> > > Reviewed-by: Simon Glass <sjg@chromium.org>
> > > Cc: Tom Rini <trini@konsulko.com>
> > > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > > Cc: Jens Wiklander <jens.wiklander@linaro.org>
> > >
> > > ---
> > >
> > > Changelog:
> > > ===============
> > >
> > > v17:
> > >
> > > * show a debug message rather than an error when FF-A is not detected
> > [snip]
> > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > index c5835e6ef6..8fbadb9201 100644
> > > --- a/lib/efi_loader/Kconfig
> > > +++ b/lib/efi_loader/Kconfig
> > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > >         stored as file /ubootefi.var on the EFI system partition.
> > >
> > >  config EFI_MM_COMM_TEE
> > > -     bool "UEFI variables storage service via OP-TEE"
> > > -     depends on OPTEE
> > > +     bool "UEFI variables storage service via the trusted world"
> > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> >
> > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > you don't make this option depend on .  If FF-A is only
> > for use here, you make FF-A depend on this, and the FF-A specific
> > variable depend on ARM_FFA_TRANSPORT.
> 
> Abdellatif hinted at what's going on here.  When I added this Kconfig
> option to lx2160 FF-A wasn't implemented yet.

The defconfig has existed since May 2020, which is when you added
EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
did until now and saw this series was disabling what was on the other
platform.

> Since FF-A isn't a new
> communication mechanism but builds upon the existing SMCs to build an
> easier API, I asked Abdellatif to hide this complexity.
> We had two options, either make Kconfig options for either FF-A or the
> traditional SMCs and remove the dependencies,  or piggyback on FF-As
> discovery mechanism and make the choice at runtime.  The latter has a
> small impact on code size, but imho makes developers' life a lot
> easier.

I'm not sure how much you can do a run-time option here since you're
setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
supposed to be able to get them at run time, we shouldn't need a Kconfig
option at all.  I'm also not sure how valid a use case it is where we
won't know at build time what the rest of the firmware stack supports
here.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-28 13:54                                                                                                                                                             ` Tom Rini
@ 2023-07-31  9:38                                                                                                                                                               ` Ilias Apalodimas
  2023-07-31 11:46                                                                                                                                                                 ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-07-31  9:38 UTC (permalink / raw)
  To: Tom Rini
  Cc: Abdellatif El Khlifi, jens.wiklander, nd, sjg, u-boot,
	Gowtham Suresh Kumar

HI Tom, 

On Fri, Jul 28, 2023 at 09:54:15AM -0400, Tom Rini wrote:
> On Fri, Jul 28, 2023 at 02:00:25PM +0300, Ilias Apalodimas wrote:
> > Hi Tom
> > 
> > On Thu, 27 Jul 2023 at 19:43, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Thu, Jul 27, 2023 at 05:07:11PM +0100, Abdellatif El Khlifi wrote:
> > >
> > > > Add MM communication support using FF-A transport
> > > >
> > > > This feature allows accessing MM partitions services through
> > > > EFI MM communication protocol. MM partitions such as StandAlonneMM
> > > > or smm-gateway secure partitions which reside in secure world.
> > > >
> > > > An MM shared buffer and a door bell event are used to exchange
> > > > the data.
> > > >
> > > > The data is used by EFI services such as GetVariable()/SetVariable()
> > > > and copied from the communication buffer to the MM shared buffer.
> > > >
> > > > The secure partition is notified about availability of data in the
> > > > MM shared buffer by an FF-A message (door bell).
> > > >
> > > > On such event, MM SP can read the data and updates the MM shared
> > > > buffer with the response data.
> > > >
> > > > The response data is copied back to the communication buffer and
> > > > consumed by the EFI subsystem.
> > > >
> > > > MM communication protocol supports FF-A 64-bit direct messaging.
> > > >
> > > > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> > > > Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
> > > > Reviewed-by: Simon Glass <sjg@chromium.org>
> > > > Cc: Tom Rini <trini@konsulko.com>
> > > > Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > > > Cc: Jens Wiklander <jens.wiklander@linaro.org>
> > > >
> > > > ---
> > > >
> > > > Changelog:
> > > > ===============
> > > >
> > > > v17:
> > > >
> > > > * show a debug message rather than an error when FF-A is not detected
> > > [snip]
> > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > index c5835e6ef6..8fbadb9201 100644
> > > > --- a/lib/efi_loader/Kconfig
> > > > +++ b/lib/efi_loader/Kconfig
> > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > >         stored as file /ubootefi.var on the EFI system partition.
> > > >
> > > >  config EFI_MM_COMM_TEE
> > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > -     depends on OPTEE
> > > > +     bool "UEFI variables storage service via the trusted world"
> > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > >
> > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > you don't make this option depend on .  If FF-A is only
> > > for use here, you make FF-A depend on this, and the FF-A specific
> > > variable depend on ARM_FFA_TRANSPORT.
> > 
> > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > option to lx2160 FF-A wasn't implemented yet.
> 
> The defconfig has existed since May 2020, which is when you added
> EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> did until now and saw this series was disabling what was on the other
> platform.
> 
> > Since FF-A isn't a new
> > communication mechanism but builds upon the existing SMCs to build an
> > easier API, I asked Abdellatif to hide this complexity.
> > We had two options, either make Kconfig options for either FF-A or the
> > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > discovery mechanism and make the choice at runtime.  The latter has a
> > small impact on code size, but imho makes developers' life a lot
> > easier.
> 
> I'm not sure how much you can do a run-time option here since you're
> setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> supposed to be able to get them at run time, we shouldn't need a Kconfig
> option at all.  I'm also not sure how valid a use case it is where we
> won't know at build time what the rest of the firmware stack supports
> here.
> 

That's a fair point.  FF-A in theory has APIs to discover memory.
Abdellatif, why do we need the Kconfigs for shared memory on FF-A?

Regards
/Ilias
> -- 
> Tom



^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-31  9:38                                                                                                                                                               ` Ilias Apalodimas
@ 2023-07-31 11:46                                                                                                                                                                 ` Abdellatif El Khlifi
  2023-07-31 17:07                                                                                                                                                                   ` Simon Glass
                                                                                                                                                                                     ` (2 more replies)
  0 siblings, 3 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-07-31 11:46 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: sjg, trini, nd, u-boot, achin.gupta

Hi Ilias,

On Mon, Jul 31, 2023 at 12:38:16PM +0300, Ilias Apalodimas wrote:
> > > > > ...
> > > > > Changelog:
> > > > > ===============
> > > > >
> > > > > v17:
> > > > >
> > > > > * show a debug message rather than an error when FF-A is not detected
> > > > [snip]
> > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > --- a/lib/efi_loader/Kconfig
> > > > > +++ b/lib/efi_loader/Kconfig
> > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > >
> > > > >  config EFI_MM_COMM_TEE
> > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > -     depends on OPTEE
> > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > >
> > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > you don't make this option depend on .  If FF-A is only
> > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > variable depend on ARM_FFA_TRANSPORT.
> > > 
> > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > option to lx2160 FF-A wasn't implemented yet.
> > 
> > The defconfig has existed since May 2020, which is when you added
> > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > did until now and saw this series was disabling what was on the other
> > platform.
> > 
> > > Since FF-A isn't a new
> > > communication mechanism but builds upon the existing SMCs to build an
> > > easier API, I asked Abdellatif to hide this complexity.
> > > We had two options, either make Kconfig options for either FF-A or the
> > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > discovery mechanism and make the choice at runtime.  The latter has a
> > > small impact on code size, but imho makes developers' life a lot
> > > easier.
> > 
> > I'm not sure how much you can do a run-time option here since you're
> > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > option at all.  I'm also not sure how valid a use case it is where we
> > won't know at build time what the rest of the firmware stack supports
> > here.
> > 
> 
> That's a fair point.  FF-A in theory has APIs to discover memory.
> Abdellatif, why do we need the Kconfigs for shared memory on FF-A?

The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
we do not implement that support currently in either U-Boot or UEFI.

Simon suggested we use build configs to set the buffer address, size and offset since we don't want
a DT node for the MM firmware.

Kind regards
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-31 11:46                                                                                                                                                                 ` Abdellatif El Khlifi
@ 2023-07-31 17:07                                                                                                                                                                   ` Simon Glass
  2023-08-01  8:24                                                                                                                                                                   ` Ilias Apalodimas
  2023-08-01 12:28                                                                                                                                                                   ` Jens Wiklander
  2 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-07-31 17:07 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: Ilias Apalodimas, trini, nd, u-boot, achin.gupta

Hi Abdellatif,

On Mon, 31 Jul 2023 at 05:46, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Hi Ilias,
>
> On Mon, Jul 31, 2023 at 12:38:16PM +0300, Ilias Apalodimas wrote:
> > > > > > ...
> > > > > > Changelog:
> > > > > > ===============
> > > > > >
> > > > > > v17:
> > > > > >
> > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > [snip]
> > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > >
> > > > > >  config EFI_MM_COMM_TEE
> > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > -     depends on OPTEE
> > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > >
> > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > you don't make this option depend on .  If FF-A is only
> > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > variable depend on ARM_FFA_TRANSPORT.
> > > >
> > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > option to lx2160 FF-A wasn't implemented yet.
> > >
> > > The defconfig has existed since May 2020, which is when you added
> > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > did until now and saw this series was disabling what was on the other
> > > platform.
> > >
> > > > Since FF-A isn't a new
> > > > communication mechanism but builds upon the existing SMCs to build an
> > > > easier API, I asked Abdellatif to hide this complexity.
> > > > We had two options, either make Kconfig options for either FF-A or the
> > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > small impact on code size, but imho makes developers' life a lot
> > > > easier.
> > >
> > > I'm not sure how much you can do a run-time option here since you're
> > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > option at all.  I'm also not sure how valid a use case it is where we
> > > won't know at build time what the rest of the firmware stack supports
> > > here.
> > >
> >
> > That's a fair point.  FF-A in theory has APIs to discover memory.
> > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
>
> The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> we do not implement that support currently in either U-Boot or UEFI.
>
> Simon suggested we use build configs to set the buffer address, size and offset since we don't want
> a DT node for the MM firmware.

Simon would really prefer that we (once and for all) get over our DT
aversion and just put it in the DT where it belongs.

But if you still don't want to do that, then falling back to Kconfig is OK.

Regards.

Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-31 11:46                                                                                                                                                                 ` Abdellatif El Khlifi
  2023-07-31 17:07                                                                                                                                                                   ` Simon Glass
@ 2023-08-01  8:24                                                                                                                                                                   ` Ilias Apalodimas
  2023-08-01 15:00                                                                                                                                                                     ` Tom Rini
  2023-08-01 12:28                                                                                                                                                                   ` Jens Wiklander
  2 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-08-01  8:24 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: sjg, trini, nd, u-boot, achin.gupta

Hi Abdellatif

On Mon, 31 Jul 2023 at 14:46, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Hi Ilias,
>
> On Mon, Jul 31, 2023 at 12:38:16PM +0300, Ilias Apalodimas wrote:
> > > > > > ...
> > > > > > Changelog:
> > > > > > ===============
> > > > > >
> > > > > > v17:
> > > > > >
> > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > [snip]
> > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > >
> > > > > >  config EFI_MM_COMM_TEE
> > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > -     depends on OPTEE
> > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > >
> > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > you don't make this option depend on .  If FF-A is only
> > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > variable depend on ARM_FFA_TRANSPORT.
> > > >
> > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > option to lx2160 FF-A wasn't implemented yet.
> > >
> > > The defconfig has existed since May 2020, which is when you added
> > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > did until now and saw this series was disabling what was on the other
> > > platform.
> > >
> > > > Since FF-A isn't a new
> > > > communication mechanism but builds upon the existing SMCs to build an
> > > > easier API, I asked Abdellatif to hide this complexity.
> > > > We had two options, either make Kconfig options for either FF-A or the
> > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > small impact on code size, but imho makes developers' life a lot
> > > > easier.
> > >
> > > I'm not sure how much you can do a run-time option here since you're
> > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > option at all.  I'm also not sure how valid a use case it is where we
> > > won't know at build time what the rest of the firmware stack supports
> > > here.
> > >
> >
> > That's a fair point.  FF-A in theory has APIs to discover memory.
> > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
>
> The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> we do not implement that support currently in either U-Boot or UEFI.

Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
addresses show up is as confusing as having Kconfig options for
discrete options.  The whole point of my suggestion was to make users'
lives easier.  Apologies for the confusion but can you bring back the
ifdefs?  Looking at the patch this should be minimal just use
ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.

Tom you prefer that as well?

Thanks
/Ilias



>
> Simon suggested we use build configs to set the buffer address, size and offset since we don't want
> a DT node for the MM firmware.
>
> Kind regards
> Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-07-31 11:46                                                                                                                                                                 ` Abdellatif El Khlifi
  2023-07-31 17:07                                                                                                                                                                   ` Simon Glass
  2023-08-01  8:24                                                                                                                                                                   ` Ilias Apalodimas
@ 2023-08-01 12:28                                                                                                                                                                   ` Jens Wiklander
  2023-08-02 10:36                                                                                                                                                                     ` Abdellatif El Khlifi
  2 siblings, 1 reply; 478+ messages in thread
From: Jens Wiklander @ 2023-08-01 12:28 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: Ilias Apalodimas, sjg, trini, nd, u-boot, achin.gupta

Hi Abdellatif,

On Mon, Jul 31, 2023 at 1:46 PM Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> Hi Ilias,
>
> On Mon, Jul 31, 2023 at 12:38:16PM +0300, Ilias Apalodimas wrote:
> > > > > > ...
> > > > > > Changelog:
> > > > > > ===============
> > > > > >
> > > > > > v17:
> > > > > >
> > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > [snip]
> > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > >
> > > > > >  config EFI_MM_COMM_TEE
> > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > -     depends on OPTEE
> > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > >
> > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > you don't make this option depend on .  If FF-A is only
> > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > variable depend on ARM_FFA_TRANSPORT.
> > > >
> > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > option to lx2160 FF-A wasn't implemented yet.
> > >
> > > The defconfig has existed since May 2020, which is when you added
> > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > did until now and saw this series was disabling what was on the other
> > > platform.
> > >
> > > > Since FF-A isn't a new
> > > > communication mechanism but builds upon the existing SMCs to build an
> > > > easier API, I asked Abdellatif to hide this complexity.
> > > > We had two options, either make Kconfig options for either FF-A or the
> > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > small impact on code size, but imho makes developers' life a lot
> > > > easier.
> > >
> > > I'm not sure how much you can do a run-time option here since you're
> > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > option at all.  I'm also not sure how valid a use case it is where we
> > > won't know at build time what the rest of the firmware stack supports
> > > here.
> > >
> >
> > That's a fair point.  FF-A in theory has APIs to discover memory.
> > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
>
> The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> we do not implement that support currently in either U-Boot or UEFI.
>
> Simon suggested we use build configs to set the buffer address, size and offset since we don't want
> a DT node for the MM firmware.

In the OP-TEE driver we're allocating memory to share dynamically
using malloc() or memalign(). Why isn't the same approach possible
here?

Thanks,
Jens

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-01  8:24                                                                                                                                                                   ` Ilias Apalodimas
@ 2023-08-01 15:00                                                                                                                                                                     ` Tom Rini
  2023-08-01 16:10                                                                                                                                                                       ` Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-08-01 15:00 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: Abdellatif El Khlifi, sjg, nd, u-boot, achin.gupta

[-- Attachment #1: Type: text/plain, Size: 4075 bytes --]

On Tue, Aug 01, 2023 at 11:24:46AM +0300, Ilias Apalodimas wrote:
> Hi Abdellatif
> 
> On Mon, 31 Jul 2023 at 14:46, Abdellatif El Khlifi
> <abdellatif.elkhlifi@arm.com> wrote:
> >
> > Hi Ilias,
> >
> > On Mon, Jul 31, 2023 at 12:38:16PM +0300, Ilias Apalodimas wrote:
> > > > > > > ...
> > > > > > > Changelog:
> > > > > > > ===============
> > > > > > >
> > > > > > > v17:
> > > > > > >
> > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > [snip]
> > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > >
> > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > -     depends on OPTEE
> > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > >
> > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > >
> > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > option to lx2160 FF-A wasn't implemented yet.
> > > >
> > > > The defconfig has existed since May 2020, which is when you added
> > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > did until now and saw this series was disabling what was on the other
> > > > platform.
> > > >
> > > > > Since FF-A isn't a new
> > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > small impact on code size, but imho makes developers' life a lot
> > > > > easier.
> > > >
> > > > I'm not sure how much you can do a run-time option here since you're
> > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > won't know at build time what the rest of the firmware stack supports
> > > > here.
> > > >
> > >
> > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> >
> > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > we do not implement that support currently in either U-Boot or UEFI.
> 
> Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> addresses show up is as confusing as having Kconfig options for
> discrete options.  The whole point of my suggestion was to make users'
> lives easier.  Apologies for the confusion but can you bring back the
> ifdefs?  Looking at the patch this should be minimal just use
> ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> 
> Tom you prefer that as well?

Pending an answer to Jens' feedback, yes, going back to #ifdef's is
fine, especially since default values of 0 are nonsense in this case
(and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
0x0 once we do string comparisons).

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-01 15:00                                                                                                                                                                     ` Tom Rini
@ 2023-08-01 16:10                                                                                                                                                                       ` Abdellatif El Khlifi
  2023-08-01 16:19                                                                                                                                                                         ` Tom Rini
  0 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-01 16:10 UTC (permalink / raw)
  To: Tom Rini, ilias.apalodimas, sjg; +Cc: achin.gupta, nd, u-boot, jens.wiklander

Hi guys,

On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > ...
> > > > > > > > Changelog:
> > > > > > > > ===============
> > > > > > > >
> > > > > > > > v17:
> > > > > > > >
> > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > [snip]
> > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > >
> > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > -     depends on OPTEE
> > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > >
> > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > >
> > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > >
> > > > > The defconfig has existed since May 2020, which is when you added
> > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > did until now and saw this series was disabling what was on the other
> > > > > platform.
> > > > >
> > > > > > Since FF-A isn't a new
> > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > easier.
> > > > >
> > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > won't know at build time what the rest of the firmware stack supports
> > > > > here.
> > > > >
> > > >
> > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > >
> > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > we do not implement that support currently in either U-Boot or UEFI.
> > 
> > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > addresses show up is as confusing as having Kconfig options for
> > discrete options.  The whole point of my suggestion was to make users'
> > lives easier.  Apologies for the confusion but can you bring back the
> > ifdefs?  Looking at the patch this should be minimal just use
> > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > 
> > Tom you prefer that as well?
> 
> Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> fine, especially since default values of 0 are nonsense in this case
> (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> 0x0 once we do string comparisons).
> 

I'd like to give some context why it's important for Corstone-1000 platform
that the DT passed to the kernel matches the official kernel DT.

There is a SystemReady IR 2.0 test checking the DT. It compares the DT
passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
to the kernel DT, the DT test will fail.

To be approved by the kernel DT maintainers, the node should have a use case
in the kernel which is not the case.

There is a solution for this which is deleting the node we don't want to pass to
the kernel using delete-node in the U-Boot DT.

This method is used by many boards in U-Boot.

Example: /delete-node/ mm-comms-buf@02000000;

Corstone-1000 can have a DT overlay that deletes the node just before running Linux (in the boot command).

If you are happy with this solution, I can do the following:

1/ create a reserved-memory memory node for Corstone-1000,
     adding mm-comms-buf sub-node which defines the buffer address, size and offset.

With this we can get rid of the configs and the #defines: FFA_SHARED_MM_BUF_ADDR,
FFA_SHARED_MM_BUF_OFFSET and FFA_SHARED_MM_BUF_SIZE.

Also, we will avoid setting 0 as default values for the address, size and offset.

2/ the FF-A specific code in efi_variable_tee.c will try to find the mm-comms-buf
reserved memory node. When found, it reads the buffer address, size and offset.

3/ adding #ifdef CONFIG_ARM_FFA_TRANSPORT in lib/efi_loader/efi_variable_tee.c
for the FF-A specific code.

4/ make EFI_MM_COMM_TEE depends on OPTEE only

What do you think guys ?

Kind regards
Abdellatif


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-01 16:10                                                                                                                                                                       ` Abdellatif El Khlifi
@ 2023-08-01 16:19                                                                                                                                                                         ` Tom Rini
  2023-08-02  6:51                                                                                                                                                                           ` Ilias Apalodimas
  2023-08-02 12:50                                                                                                                                                                           ` [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication Simon Glass
  0 siblings, 2 replies; 478+ messages in thread
From: Tom Rini @ 2023-08-01 16:19 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: ilias.apalodimas, sjg, achin.gupta, nd, u-boot, jens.wiklander

[-- Attachment #1: Type: text/plain, Size: 6195 bytes --]

On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> Hi guys,
> 
> On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > ...
> > > > > > > > > Changelog:
> > > > > > > > > ===============
> > > > > > > > >
> > > > > > > > > v17:
> > > > > > > > >
> > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > [snip]
> > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > >
> > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > -     depends on OPTEE
> > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > >
> > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > >
> > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > >
> > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > did until now and saw this series was disabling what was on the other
> > > > > > platform.
> > > > > >
> > > > > > > Since FF-A isn't a new
> > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > easier.
> > > > > >
> > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > here.
> > > > > >
> > > > >
> > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > >
> > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > we do not implement that support currently in either U-Boot or UEFI.
> > > 
> > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > addresses show up is as confusing as having Kconfig options for
> > > discrete options.  The whole point of my suggestion was to make users'
> > > lives easier.  Apologies for the confusion but can you bring back the
> > > ifdefs?  Looking at the patch this should be minimal just use
> > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > 
> > > Tom you prefer that as well?
> > 
> > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > fine, especially since default values of 0 are nonsense in this case
> > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > 0x0 once we do string comparisons).
> > 
> 
> I'd like to give some context why it's important for Corstone-1000 platform
> that the DT passed to the kernel matches the official kernel DT.

Note that we've set aside the "should this be in DT or not" question.

> There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> to the kernel DT, the DT test will fail.

This is overall good and progress.

> To be approved by the kernel DT maintainers, the node should have a use case
> in the kernel which is not the case.

This is, I believe / hope wrong.  It needs to be in the dt-schema
repository, not strictly "the kernel".  For example, bootph-all (etc)
are in dt-schema and so can be in the upstream kernel but are not used
in the kernel itself.

> There is a solution for this which is deleting the node we don't want to pass to
> the kernel using delete-node in the U-Boot DT.

Something like this will likely be needed, in the end, at least for some
cases.  But the goal is that everything gets in to dt-schema.

[snip]
> With this we can get rid of the configs and the #defines: FFA_SHARED_MM_BUF_ADDR,
> FFA_SHARED_MM_BUF_OFFSET and FFA_SHARED_MM_BUF_SIZE.
> 
> Also, we will avoid setting 0 as default values for the address, size and offset.

We just need to not have default values offered.  The symbols just need
to depend on FFA so that they aren't asked when not used.

> 2/ the FF-A specific code in efi_variable_tee.c will try to find the mm-comms-buf
> reserved memory node. When found, it reads the buffer address, size and offset.
> 
> 3/ adding #ifdef CONFIG_ARM_FFA_TRANSPORT in lib/efi_loader/efi_variable_tee.c
> for the FF-A specific code.
> 
> 4/ make EFI_MM_COMM_TEE depends on OPTEE only
> 
> What do you think guys ?

Yes, we need to do 3 and 4.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-01 16:19                                                                                                                                                                         ` Tom Rini
@ 2023-08-02  6:51                                                                                                                                                                           ` Ilias Apalodimas
  2023-08-02 12:52                                                                                                                                                                             ` Simon Glass
  2023-08-03 16:03                                                                                                                                                                             ` [PATCH v18 0/9] introduce Arm FF-A support Abdellatif El Khlifi
  2023-08-02 12:50                                                                                                                                                                           ` [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication Simon Glass
  1 sibling, 2 replies; 478+ messages in thread
From: Ilias Apalodimas @ 2023-08-02  6:51 UTC (permalink / raw)
  To: Tom Rini
  Cc: Abdellatif El Khlifi, sjg, achin.gupta, nd, u-boot, jens.wiklander

On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
>
> On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > Hi guys,
> >
> > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > ...
> > > > > > > > > > Changelog:
> > > > > > > > > > ===============
> > > > > > > > > >
> > > > > > > > > > v17:
> > > > > > > > > >
> > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > [snip]
> > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > >
> > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > >
> > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > >
> > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > >
> > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > platform.
> > > > > > >
> > > > > > > > Since FF-A isn't a new
> > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > easier.
> > > > > > >
> > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > here.
> > > > > > >
> > > > > >
> > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > >
> > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > >
> > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > addresses show up is as confusing as having Kconfig options for
> > > > discrete options.  The whole point of my suggestion was to make users'
> > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > >
> > > > Tom you prefer that as well?
> > >
> > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > fine, especially since default values of 0 are nonsense in this case
> > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > 0x0 once we do string comparisons).
> > >
> >
> > I'd like to give some context why it's important for Corstone-1000 platform
> > that the DT passed to the kernel matches the official kernel DT.
>
> Note that we've set aside the "should this be in DT or not" question.
>
> > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > to the kernel DT, the DT test will fail.
>
> This is overall good and progress.
>
> > To be approved by the kernel DT maintainers, the node should have a use case
> > in the kernel which is not the case.
>
> This is, I believe / hope wrong.  It needs to be in the dt-schema
> repository, not strictly "the kernel".  For example, bootph-all (etc)
> are in dt-schema and so can be in the upstream kernel but are not used
> in the kernel itself.
>
> > There is a solution for this which is deleting the node we don't want to pass to
> > the kernel using delete-node in the U-Boot DT.
>
> Something like this will likely be needed, in the end, at least for some
> cases.  But the goal is that everything gets in to dt-schema.

We are already working on U-Boot on that.  The idea is rather simple.
We will have an array with nodes and node entries.  Before we boot up
we'll scan that array, if a node entry exists we will delete that,
otherwise we will just get rid of the entire node.  That should be
pretty easy to maintain and extend.  U-Boot will then be able to use
it;s internal bidings without polluting the DT we handover to the
kernel.

I think you should just wait for that patch instead of hacking the boot cmd.

>
> [snip]
> > With this we can get rid of the configs and the #defines: FFA_SHARED_MM_BUF_ADDR,
> > FFA_SHARED_MM_BUF_OFFSET and FFA_SHARED_MM_BUF_SIZE.
> >
> > Also, we will avoid setting 0 as default values for the address, size and offset.
>
> We just need to not have default values offered.  The symbols just need
> to depend on FFA so that they aren't asked when not used.
>
> > 2/ the FF-A specific code in efi_variable_tee.c will try to find the mm-comms-buf
> > reserved memory node. When found, it reads the buffer address, size and offset.
> >
> > 3/ adding #ifdef CONFIG_ARM_FFA_TRANSPORT in lib/efi_loader/efi_variable_tee.c
> > for the FF-A specific code.
> >
> > 4/ make EFI_MM_COMM_TEE depends on OPTEE only
> >
> > What do you think guys ?
>
> Yes, we need to do 3 and 4.

+1 here

Thanks
/Ilias
>
> --
> Tom

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-01 12:28                                                                                                                                                                   ` Jens Wiklander
@ 2023-08-02 10:36                                                                                                                                                                     ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-02 10:36 UTC (permalink / raw)
  To: Jens Wiklander; +Cc: achin.gupta, nd, u-boot

Hi Jens,

On Tue, Aug 01, 2023 at 02:28:34PM +0200, Jens Wiklander wrote:
> > > > > > > ...
> > > > > > > Changelog:
> > > > > > > ===============
> > > > > > >
> > > > > > > v17:
> > > > > > >
> > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > [snip]
> > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > >
> > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > -     depends on OPTEE
> > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > >
> > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > >
> > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > option to lx2160 FF-A wasn't implemented yet.
> > > >
> > > > The defconfig has existed since May 2020, which is when you added
> > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > did until now and saw this series was disabling what was on the other
> > > > platform.
> > > >
> > > > > Since FF-A isn't a new
> > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > small impact on code size, but imho makes developers' life a lot
> > > > > easier.
> > > >
> > > > I'm not sure how much you can do a run-time option here since you're
> > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > won't know at build time what the rest of the firmware stack supports
> > > > here.
> > > >
> > >
> > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> >
> > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > we do not implement that support currently in either U-Boot or UEFI.
> >
> > Simon suggested we use build configs to set the buffer address, size and offset since we don't want
> > a DT node for the MM firmware.
> 
> In the OP-TEE driver we're allocating memory to share dynamically
> using malloc() or memalign(). Why isn't the same approach possible
> here?
> 

FF-A memory sharing can not be used because the MM SP needs to know the layout
of the MM communication buffer during initialisation. This happens before the Normal world
has got a chance to run. So we have a chicken and egg and Normal World cannot use FF-A ABIs
to share the buffer as things stand.

Cheers,
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-01 16:19                                                                                                                                                                         ` Tom Rini
  2023-08-02  6:51                                                                                                                                                                           ` Ilias Apalodimas
@ 2023-08-02 12:50                                                                                                                                                                           ` Simon Glass
  1 sibling, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-08-02 12:50 UTC (permalink / raw)
  To: Tom Rini
  Cc: Abdellatif El Khlifi, ilias.apalodimas, achin.gupta, nd, u-boot,
	jens.wiklander

Hi,

On Tue, 1 Aug 2023 at 10:19, Tom Rini <trini@konsulko.com> wrote:
>
> On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > Hi guys,
> >
> > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > ...
> > > > > > > > > > Changelog:
> > > > > > > > > > ===============
> > > > > > > > > >
> > > > > > > > > > v17:
> > > > > > > > > >
> > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > [snip]
> > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > >
> > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > >
> > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > >
> > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > >
> > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > platform.
> > > > > > >
> > > > > > > > Since FF-A isn't a new
> > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > easier.
> > > > > > >
> > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > here.
> > > > > > >
> > > > > >
> > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > >
> > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > >
> > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > addresses show up is as confusing as having Kconfig options for
> > > > discrete options.  The whole point of my suggestion was to make users'
> > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > >
> > > > Tom you prefer that as well?
> > >
> > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > fine, especially since default values of 0 are nonsense in this case
> > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > 0x0 once we do string comparisons).
> > >
> >
> > I'd like to give some context why it's important for Corstone-1000 platform
> > that the DT passed to the kernel matches the official kernel DT.
>
> Note that we've set aside the "should this be in DT or not" question.
>
> > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > to the kernel DT, the DT test will fail.
>
> This is overall good and progress.

Yes, great to hear.

>
> > To be approved by the kernel DT maintainers, the node should have a use case
> > in the kernel which is not the case.
>
> This is, I believe / hope wrong.  It needs to be in the dt-schema
> repository, not strictly "the kernel".  For example, bootph-all (etc)
> are in dt-schema and so can be in the upstream kernel but are not used
> in the kernel itself.

Indeed. How do we get this message out, since there still seems to be
some confusion here. Should we do an announcement on LKML, perhaps?

>
> > There is a solution for this which is deleting the node we don't want to pass to
> > the kernel using delete-node in the U-Boot DT.
>
> Something like this will likely be needed, in the end, at least for some
> cases.  But the goal is that everything gets in to dt-schema.
>
> [snip]
> > With this we can get rid of the configs and the #defines: FFA_SHARED_MM_BUF_ADDR,
> > FFA_SHARED_MM_BUF_OFFSET and FFA_SHARED_MM_BUF_SIZE.
> >
> > Also, we will avoid setting 0 as default values for the address, size and offset.
>
> We just need to not have default values offered.  The symbols just need
> to depend on FFA so that they aren't asked when not used.
>
> > 2/ the FF-A specific code in efi_variable_tee.c will try to find the mm-comms-buf
> > reserved memory node. When found, it reads the buffer address, size and offset.
> >
> > 3/ adding #ifdef CONFIG_ARM_FFA_TRANSPORT in lib/efi_loader/efi_variable_tee.c
> > for the FF-A specific code.
> >
> > 4/ make EFI_MM_COMM_TEE depends on OPTEE only
> >
> > What do you think guys ?
>
> Yes, we need to do 3 and 4.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02  6:51                                                                                                                                                                           ` Ilias Apalodimas
@ 2023-08-02 12:52                                                                                                                                                                             ` Simon Glass
  2023-08-02 13:02                                                                                                                                                                               ` Ilias Apalodimas
  2023-08-03 16:03                                                                                                                                                                             ` [PATCH v18 0/9] introduce Arm FF-A support Abdellatif El Khlifi
  1 sibling, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-08-02 12:52 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, nd, u-boot, jens.wiklander

Hi Ilias,

On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > Hi guys,
> > >
> > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > ...
> > > > > > > > > > > Changelog:
> > > > > > > > > > > ===============
> > > > > > > > > > >
> > > > > > > > > > > v17:
> > > > > > > > > > >
> > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > [snip]
> > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > >
> > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > >
> > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > >
> > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > >
> > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > platform.
> > > > > > > >
> > > > > > > > > Since FF-A isn't a new
> > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > easier.
> > > > > > > >
> > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > here.
> > > > > > > >
> > > > > > >
> > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > >
> > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > >
> > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > addresses show up is as confusing as having Kconfig options for
> > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > >
> > > > > Tom you prefer that as well?
> > > >
> > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > fine, especially since default values of 0 are nonsense in this case
> > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > 0x0 once we do string comparisons).
> > > >
> > >
> > > I'd like to give some context why it's important for Corstone-1000 platform
> > > that the DT passed to the kernel matches the official kernel DT.
> >
> > Note that we've set aside the "should this be in DT or not" question.
> >
> > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > to the kernel DT, the DT test will fail.
> >
> > This is overall good and progress.
> >
> > > To be approved by the kernel DT maintainers, the node should have a use case
> > > in the kernel which is not the case.
> >
> > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > are in dt-schema and so can be in the upstream kernel but are not used
> > in the kernel itself.
> >
> > > There is a solution for this which is deleting the node we don't want to pass to
> > > the kernel using delete-node in the U-Boot DT.
> >
> > Something like this will likely be needed, in the end, at least for some
> > cases.  But the goal is that everything gets in to dt-schema.
>
> We are already working on U-Boot on that.  The idea is rather simple.
> We will have an array with nodes and node entries.  Before we boot up
> we'll scan that array, if a node entry exists we will delete that,
> otherwise we will just get rid of the entire node.  That should be
> pretty easy to maintain and extend.  U-Boot will then be able to use
> it;s internal bidings without polluting the DT we handover to the
> kernel.

This is not pollution - we have moved past that now and Linux has
accepted some U-Boot bindings. This is the DT and if there are things
in it that are not related to Linux, it can ignore them.

We should add whatever bindings we need to make U-Boot work
efficiently and correctly.

>
> I think you should just wait for that patch instead of hacking the boot cmd.
>
> >
> > [snip]
> > > With this we can get rid of the configs and the #defines: FFA_SHARED_MM_BUF_ADDR,
> > > FFA_SHARED_MM_BUF_OFFSET and FFA_SHARED_MM_BUF_SIZE.
> > >
> > > Also, we will avoid setting 0 as default values for the address, size and offset.
> >
> > We just need to not have default values offered.  The symbols just need
> > to depend on FFA so that they aren't asked when not used.
> >
> > > 2/ the FF-A specific code in efi_variable_tee.c will try to find the mm-comms-buf
> > > reserved memory node. When found, it reads the buffer address, size and offset.
> > >
> > > 3/ adding #ifdef CONFIG_ARM_FFA_TRANSPORT in lib/efi_loader/efi_variable_tee.c
> > > for the FF-A specific code.
> > >
> > > 4/ make EFI_MM_COMM_TEE depends on OPTEE only
> > >
> > > What do you think guys ?
> >
> > Yes, we need to do 3 and 4.
>
> +1 here

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02 12:52                                                                                                                                                                             ` Simon Glass
@ 2023-08-02 13:02                                                                                                                                                                               ` Ilias Apalodimas
  2023-08-02 13:08                                                                                                                                                                                 ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-08-02 13:02 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, nd, u-boot, jens.wiklander

Hi Simon,

On Wed, 2 Aug 2023 at 15:52, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Ilias,
>
> On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > > Hi guys,
> > > >
> > > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > > ...
> > > > > > > > > > > > Changelog:
> > > > > > > > > > > > ===============
> > > > > > > > > > > >
> > > > > > > > > > > > v17:
> > > > > > > > > > > >
> > > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > > [snip]
> > > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > > >
> > > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > > >
> > > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > > >
> > > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > > >
> > > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > > platform.
> > > > > > > > >
> > > > > > > > > > Since FF-A isn't a new
> > > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > > easier.
> > > > > > > > >
> > > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > > here.
> > > > > > > > >
> > > > > > > >
> > > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > > >
> > > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > > >
> > > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > > addresses show up is as confusing as having Kconfig options for
> > > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > > >
> > > > > > Tom you prefer that as well?
> > > > >
> > > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > > fine, especially since default values of 0 are nonsense in this case
> > > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > > 0x0 once we do string comparisons).
> > > > >
> > > >
> > > > I'd like to give some context why it's important for Corstone-1000 platform
> > > > that the DT passed to the kernel matches the official kernel DT.
> > >
> > > Note that we've set aside the "should this be in DT or not" question.
> > >
> > > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > > to the kernel DT, the DT test will fail.
> > >
> > > This is overall good and progress.
> > >
> > > > To be approved by the kernel DT maintainers, the node should have a use case
> > > > in the kernel which is not the case.
> > >
> > > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > > are in dt-schema and so can be in the upstream kernel but are not used
> > > in the kernel itself.
> > >
> > > > There is a solution for this which is deleting the node we don't want to pass to
> > > > the kernel using delete-node in the U-Boot DT.
> > >
> > > Something like this will likely be needed, in the end, at least for some
> > > cases.  But the goal is that everything gets in to dt-schema.
> >
> > We are already working on U-Boot on that.  The idea is rather simple.
> > We will have an array with nodes and node entries.  Before we boot up
> > we'll scan that array, if a node entry exists we will delete that,
> > otherwise we will just get rid of the entire node.  That should be
> > pretty easy to maintain and extend.  U-Boot will then be able to use
> > it;s internal bidings without polluting the DT we handover to the
> > kernel.
>
> This is not pollution - we have moved past that now and Linux has
> accepted some U-Boot bindings. This is the DT and if there are things
> in it that are not related to Linux, it can ignore them.
>
> We should add whatever bindings we need to make U-Boot work
> efficiently and correctly.
>

The cases that are already accepted make sense.  Things like the
public part of the certificates used to authenticate capsule updates
or the encoding of the recent a/b update nodes are not needed in any
way in an OS.  Those don't make sense to upstream and those are
polluting the DT and need stripping

Regards
/Ilias


> >
> > I think you should just wait for that patch instead of hacking the boot cmd.
> >
> > >
> > > [snip]
> > > > With this we can get rid of the configs and the #defines: FFA_SHARED_MM_BUF_ADDR,
> > > > FFA_SHARED_MM_BUF_OFFSET and FFA_SHARED_MM_BUF_SIZE.
> > > >
> > > > Also, we will avoid setting 0 as default values for the address, size and offset.
> > >
> > > We just need to not have default values offered.  The symbols just need
> > > to depend on FFA so that they aren't asked when not used.
> > >
> > > > 2/ the FF-A specific code in efi_variable_tee.c will try to find the mm-comms-buf
> > > > reserved memory node. When found, it reads the buffer address, size and offset.
> > > >
> > > > 3/ adding #ifdef CONFIG_ARM_FFA_TRANSPORT in lib/efi_loader/efi_variable_tee.c
> > > > for the FF-A specific code.
> > > >
> > > > 4/ make EFI_MM_COMM_TEE depends on OPTEE only
> > > >
> > > > What do you think guys ?
> > >
> > > Yes, we need to do 3 and 4.
> >
> > +1 here
>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02 13:02                                                                                                                                                                               ` Ilias Apalodimas
@ 2023-08-02 13:08                                                                                                                                                                                 ` Simon Glass
  2023-08-02 13:26                                                                                                                                                                                   ` Ilias Apalodimas
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-08-02 13:08 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, nd, u-boot, jens.wiklander

Hi Ilias,

On Wed, 2 Aug 2023 at 07:02, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Simon,
>
> On Wed, 2 Aug 2023 at 15:52, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Ilias,
> >
> > On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
> > <ilias.apalodimas@linaro.org> wrote:
> > >
> > > On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > > > Hi guys,
> > > > >
> > > > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > > > ...
> > > > > > > > > > > > > Changelog:
> > > > > > > > > > > > > ===============
> > > > > > > > > > > > >
> > > > > > > > > > > > > v17:
> > > > > > > > > > > > >
> > > > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > > > [snip]
> > > > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > > > >
> > > > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > > > >
> > > > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > > > >
> > > > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > > > >
> > > > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > > > platform.
> > > > > > > > > >
> > > > > > > > > > > Since FF-A isn't a new
> > > > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > > > easier.
> > > > > > > > > >
> > > > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > > > here.
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > > > >
> > > > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > > > >
> > > > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > > > addresses show up is as confusing as having Kconfig options for
> > > > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > > > >
> > > > > > > Tom you prefer that as well?
> > > > > >
> > > > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > > > fine, especially since default values of 0 are nonsense in this case
> > > > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > > > 0x0 once we do string comparisons).
> > > > > >
> > > > >
> > > > > I'd like to give some context why it's important for Corstone-1000 platform
> > > > > that the DT passed to the kernel matches the official kernel DT.
> > > >
> > > > Note that we've set aside the "should this be in DT or not" question.
> > > >
> > > > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > > > to the kernel DT, the DT test will fail.
> > > >
> > > > This is overall good and progress.
> > > >
> > > > > To be approved by the kernel DT maintainers, the node should have a use case
> > > > > in the kernel which is not the case.
> > > >
> > > > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > > > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > > > are in dt-schema and so can be in the upstream kernel but are not used
> > > > in the kernel itself.
> > > >
> > > > > There is a solution for this which is deleting the node we don't want to pass to
> > > > > the kernel using delete-node in the U-Boot DT.
> > > >
> > > > Something like this will likely be needed, in the end, at least for some
> > > > cases.  But the goal is that everything gets in to dt-schema.
> > >
> > > We are already working on U-Boot on that.  The idea is rather simple.
> > > We will have an array with nodes and node entries.  Before we boot up
> > > we'll scan that array, if a node entry exists we will delete that,
> > > otherwise we will just get rid of the entire node.  That should be
> > > pretty easy to maintain and extend.  U-Boot will then be able to use
> > > it;s internal bidings without polluting the DT we handover to the
> > > kernel.
> >
> > This is not pollution - we have moved past that now and Linux has
> > accepted some U-Boot bindings. This is the DT and if there are things
> > in it that are not related to Linux, it can ignore them.
> >
> > We should add whatever bindings we need to make U-Boot work
> > efficiently and correctly.
> >
>
> The cases that are already accepted make sense.  Things like the
> public part of the certificates used to authenticate capsule updates
> or the encoding of the recent a/b update nodes are not needed in any
> way in an OS.  Those don't make sense to upstream and those are
> polluting the DT and need stripping

It doesn't matter that Linux doesn't *need* it. If it is there it will
have to accommodate it. We have loads of Linux stuff in the DT that
means nothing to U-Boot. Many of the bindings chosen by Linux are
wildly inefficient for U-Boot to implement.

We don't need to strip anything. This is not pollution. It is a
binding agreement between projects.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02 13:08                                                                                                                                                                                 ` Simon Glass
@ 2023-08-02 13:26                                                                                                                                                                                   ` Ilias Apalodimas
  2023-08-02 13:34                                                                                                                                                                                     ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-08-02 13:26 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, nd, u-boot, jens.wiklander

Hi Simon,


On Wed, 2 Aug 2023 at 16:09, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Ilias,
>
> On Wed, 2 Aug 2023 at 07:02, Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > Hi Simon,
> >
> > On Wed, 2 Aug 2023 at 15:52, Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Ilias,
> > >
> > > On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
> > > <ilias.apalodimas@linaro.org> wrote:
> > > >
> > > > On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> > > > >
> > > > > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > > > > Hi guys,
> > > > > >
> > > > > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > > > > ...
> > > > > > > > > > > > > > Changelog:
> > > > > > > > > > > > > > ===============
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > v17:
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > > > > [snip]
> > > > > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > > > > >
> > > > > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > > > > >
> > > > > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > > > > >
> > > > > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > > > > platform.
> > > > > > > > > > >
> > > > > > > > > > > > Since FF-A isn't a new
> > > > > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > > > > easier.
> > > > > > > > > > >
> > > > > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > > > > here.
> > > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > > > > >
> > > > > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > > > > >
> > > > > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > > > > addresses show up is as confusing as having Kconfig options for
> > > > > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > > > > >
> > > > > > > > Tom you prefer that as well?
> > > > > > >
> > > > > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > > > > fine, especially since default values of 0 are nonsense in this case
> > > > > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > > > > 0x0 once we do string comparisons).
> > > > > > >
> > > > > >
> > > > > > I'd like to give some context why it's important for Corstone-1000 platform
> > > > > > that the DT passed to the kernel matches the official kernel DT.
> > > > >
> > > > > Note that we've set aside the "should this be in DT or not" question.
> > > > >
> > > > > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > > > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > > > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > > > > to the kernel DT, the DT test will fail.
> > > > >
> > > > > This is overall good and progress.
> > > > >
> > > > > > To be approved by the kernel DT maintainers, the node should have a use case
> > > > > > in the kernel which is not the case.
> > > > >
> > > > > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > > > > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > > > > are in dt-schema and so can be in the upstream kernel but are not used
> > > > > in the kernel itself.
> > > > >
> > > > > > There is a solution for this which is deleting the node we don't want to pass to
> > > > > > the kernel using delete-node in the U-Boot DT.
> > > > >
> > > > > Something like this will likely be needed, in the end, at least for some
> > > > > cases.  But the goal is that everything gets in to dt-schema.
> > > >
> > > > We are already working on U-Boot on that.  The idea is rather simple.
> > > > We will have an array with nodes and node entries.  Before we boot up
> > > > we'll scan that array, if a node entry exists we will delete that,
> > > > otherwise we will just get rid of the entire node.  That should be
> > > > pretty easy to maintain and extend.  U-Boot will then be able to use
> > > > it;s internal bidings without polluting the DT we handover to the
> > > > kernel.
> > >
> > > This is not pollution - we have moved past that now and Linux has
> > > accepted some U-Boot bindings. This is the DT and if there are things
> > > in it that are not related to Linux, it can ignore them.
> > >
> > > We should add whatever bindings we need to make U-Boot work
> > > efficiently and correctly.
> > >
> >
> > The cases that are already accepted make sense.  Things like the
> > public part of the certificates used to authenticate capsule updates
> > or the encoding of the recent a/b update nodes are not needed in any
> > way in an OS.  Those don't make sense to upstream and those are
> > polluting the DT and need stripping
>
> It doesn't matter that Linux doesn't *need* it. If it is there it will
> have to accommodate it. We have loads of Linux stuff in the DT that
> means nothing to U-Boot. Many of the bindings chosen by Linux are
> wildly inefficient for U-Boot to implement.
>
> We don't need to strip anything. This is not pollution. It is a
> binding agreement between projects.
>

I am not a maintainer, but I doubt they view it that way.  In any
case, the DT produced by u-boot fails to pass the certification on
every single platform that uses nonupstream nodes, so cleaning that up
is needed.  If people care enough and upstream those bindings we can
preserve them

Thanks
/Ilias
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02 13:26                                                                                                                                                                                   ` Ilias Apalodimas
@ 2023-08-02 13:34                                                                                                                                                                                     ` Simon Glass
  2023-08-02 13:37                                                                                                                                                                                       ` Ilias Apalodimas
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-08-02 13:34 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, nd, u-boot, jens.wiklander

Hi Ilias,

On Wed, 2 Aug 2023 at 07:27, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Simon,
>
>
> On Wed, 2 Aug 2023 at 16:09, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Ilias,
> >
> > On Wed, 2 Aug 2023 at 07:02, Ilias Apalodimas
> > <ilias.apalodimas@linaro.org> wrote:
> > >
> > > Hi Simon,
> > >
> > > On Wed, 2 Aug 2023 at 15:52, Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Ilias,
> > > >
> > > > On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
> > > > <ilias.apalodimas@linaro.org> wrote:
> > > > >
> > > > > On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> > > > > >
> > > > > > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > > > > > Hi guys,
> > > > > > >
> > > > > > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > > > > > ...
> > > > > > > > > > > > > > > Changelog:
> > > > > > > > > > > > > > > ===============
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > v17:
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > > > > > [snip]
> > > > > > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > > > > > >
> > > > > > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > > > > > platform.
> > > > > > > > > > > >
> > > > > > > > > > > > > Since FF-A isn't a new
> > > > > > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > > > > > easier.
> > > > > > > > > > > >
> > > > > > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > > > > > here.
> > > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > > > > > >
> > > > > > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > > > > > >
> > > > > > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > > > > > addresses show up is as confusing as having Kconfig options for
> > > > > > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > > > > > >
> > > > > > > > > Tom you prefer that as well?
> > > > > > > >
> > > > > > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > > > > > fine, especially since default values of 0 are nonsense in this case
> > > > > > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > > > > > 0x0 once we do string comparisons).
> > > > > > > >
> > > > > > >
> > > > > > > I'd like to give some context why it's important for Corstone-1000 platform
> > > > > > > that the DT passed to the kernel matches the official kernel DT.
> > > > > >
> > > > > > Note that we've set aside the "should this be in DT or not" question.
> > > > > >
> > > > > > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > > > > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > > > > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > > > > > to the kernel DT, the DT test will fail.
> > > > > >
> > > > > > This is overall good and progress.
> > > > > >
> > > > > > > To be approved by the kernel DT maintainers, the node should have a use case
> > > > > > > in the kernel which is not the case.
> > > > > >
> > > > > > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > > > > > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > > > > > are in dt-schema and so can be in the upstream kernel but are not used
> > > > > > in the kernel itself.
> > > > > >
> > > > > > > There is a solution for this which is deleting the node we don't want to pass to
> > > > > > > the kernel using delete-node in the U-Boot DT.
> > > > > >
> > > > > > Something like this will likely be needed, in the end, at least for some
> > > > > > cases.  But the goal is that everything gets in to dt-schema.
> > > > >
> > > > > We are already working on U-Boot on that.  The idea is rather simple.
> > > > > We will have an array with nodes and node entries.  Before we boot up
> > > > > we'll scan that array, if a node entry exists we will delete that,
> > > > > otherwise we will just get rid of the entire node.  That should be
> > > > > pretty easy to maintain and extend.  U-Boot will then be able to use
> > > > > it;s internal bidings without polluting the DT we handover to the
> > > > > kernel.
> > > >
> > > > This is not pollution - we have moved past that now and Linux has
> > > > accepted some U-Boot bindings. This is the DT and if there are things
> > > > in it that are not related to Linux, it can ignore them.
> > > >
> > > > We should add whatever bindings we need to make U-Boot work
> > > > efficiently and correctly.
> > > >
> > >
> > > The cases that are already accepted make sense.  Things like the
> > > public part of the certificates used to authenticate capsule updates
> > > or the encoding of the recent a/b update nodes are not needed in any
> > > way in an OS.  Those don't make sense to upstream and those are
> > > polluting the DT and need stripping
> >
> > It doesn't matter that Linux doesn't *need* it. If it is there it will
> > have to accommodate it. We have loads of Linux stuff in the DT that
> > means nothing to U-Boot. Many of the bindings chosen by Linux are
> > wildly inefficient for U-Boot to implement.
> >
> > We don't need to strip anything. This is not pollution. It is a
> > binding agreement between projects.
> >
>
> I am not a maintainer, but I doubt they view it that way.  In any

Who?

> case, the DT produced by u-boot fails to pass the certification on

U-Boot

> every single platform that uses nonupstream nodes, so cleaning that up
> is needed.  If people care enough and upstream those bindings we can
> preserve them

Yes I agree, and the bindings that are added need to be upstream in
dt-schema. This applies also to the work that Linaro does.

I will mention this to Sugosh as well as he is adding a public key.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02 13:34                                                                                                                                                                                     ` Simon Glass
@ 2023-08-02 13:37                                                                                                                                                                                       ` Ilias Apalodimas
  2023-08-02 13:41                                                                                                                                                                                         ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-08-02 13:37 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, nd, u-boot, jens.wiklander

Hi Simon,

On Wed, 2 Aug 2023 at 16:34, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Ilias,
>
> On Wed, 2 Aug 2023 at 07:27, Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > Hi Simon,
> >
> >
> > On Wed, 2 Aug 2023 at 16:09, Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Ilias,
> > >
> > > On Wed, 2 Aug 2023 at 07:02, Ilias Apalodimas
> > > <ilias.apalodimas@linaro.org> wrote:
> > > >
> > > > Hi Simon,
> > > >
> > > > On Wed, 2 Aug 2023 at 15:52, Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > Hi Ilias,
> > > > >
> > > > > On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
> > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > >
> > > > > > On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> > > > > > >
> > > > > > > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > > > > > > Hi guys,
> > > > > > > >
> > > > > > > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > > > > > > ...
> > > > > > > > > > > > > > > > Changelog:
> > > > > > > > > > > > > > > > ===============
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > v17:
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > > > > > > [snip]
> > > > > > > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > > > > > > >
> > > > > > > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > > > > > > platform.
> > > > > > > > > > > > >
> > > > > > > > > > > > > > Since FF-A isn't a new
> > > > > > > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > > > > > > easier.
> > > > > > > > > > > > >
> > > > > > > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > > > > > > here.
> > > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > > > > > > >
> > > > > > > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > > > > > > >
> > > > > > > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > > > > > > addresses show up is as confusing as having Kconfig options for
> > > > > > > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > > > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > > > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > > > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > > > > > > >
> > > > > > > > > > Tom you prefer that as well?
> > > > > > > > >
> > > > > > > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > > > > > > fine, especially since default values of 0 are nonsense in this case
> > > > > > > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > > > > > > 0x0 once we do string comparisons).
> > > > > > > > >
> > > > > > > >
> > > > > > > > I'd like to give some context why it's important for Corstone-1000 platform
> > > > > > > > that the DT passed to the kernel matches the official kernel DT.
> > > > > > >
> > > > > > > Note that we've set aside the "should this be in DT or not" question.
> > > > > > >
> > > > > > > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > > > > > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > > > > > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > > > > > > to the kernel DT, the DT test will fail.
> > > > > > >
> > > > > > > This is overall good and progress.
> > > > > > >
> > > > > > > > To be approved by the kernel DT maintainers, the node should have a use case
> > > > > > > > in the kernel which is not the case.
> > > > > > >
> > > > > > > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > > > > > > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > > > > > > are in dt-schema and so can be in the upstream kernel but are not used
> > > > > > > in the kernel itself.
> > > > > > >
> > > > > > > > There is a solution for this which is deleting the node we don't want to pass to
> > > > > > > > the kernel using delete-node in the U-Boot DT.
> > > > > > >
> > > > > > > Something like this will likely be needed, in the end, at least for some
> > > > > > > cases.  But the goal is that everything gets in to dt-schema.
> > > > > >
> > > > > > We are already working on U-Boot on that.  The idea is rather simple.
> > > > > > We will have an array with nodes and node entries.  Before we boot up
> > > > > > we'll scan that array, if a node entry exists we will delete that,
> > > > > > otherwise we will just get rid of the entire node.  That should be
> > > > > > pretty easy to maintain and extend.  U-Boot will then be able to use
> > > > > > it;s internal bidings without polluting the DT we handover to the
> > > > > > kernel.
> > > > >
> > > > > This is not pollution - we have moved past that now and Linux has
> > > > > accepted some U-Boot bindings. This is the DT and if there are things
> > > > > in it that are not related to Linux, it can ignore them.
> > > > >
> > > > > We should add whatever bindings we need to make U-Boot work
> > > > > efficiently and correctly.
> > > > >
> > > >
> > > > The cases that are already accepted make sense.  Things like the
> > > > public part of the certificates used to authenticate capsule updates
> > > > or the encoding of the recent a/b update nodes are not needed in any
> > > > way in an OS.  Those don't make sense to upstream and those are
> > > > polluting the DT and need stripping
> > >
> > > It doesn't matter that Linux doesn't *need* it. If it is there it will
> > > have to accommodate it. We have loads of Linux stuff in the DT that
> > > means nothing to U-Boot. Many of the bindings chosen by Linux are
> > > wildly inefficient for U-Boot to implement.
> > >
> > > We don't need to strip anything. This is not pollution. It is a
> > > binding agreement between projects.
> > >
> >
> > I am not a maintainer, but I doubt they view it that way.  In any
>
> Who?
>
> > case, the DT produced by u-boot fails to pass the certification on
>
> U-Boot
>
> > every single platform that uses nonupstream nodes, so cleaning that up
> > is needed.  If people care enough and upstream those bindings we can
> > preserve them
>
> Yes I agree, and the bindings that are added need to be upstream in
> dt-schema. This applies also to the work that Linaro does.
>
> I will mention this to Sugosh as well as he is adding a public key.

He is already aware, he is working on a PoC that does exactly what I
described.  Once we verify devices are starting to pass the
SystemReady2.0 certification he will send an RFC

Regards
/Ilias
>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02 13:37                                                                                                                                                                                       ` Ilias Apalodimas
@ 2023-08-02 13:41                                                                                                                                                                                         ` Simon Glass
  2023-08-02 13:42                                                                                                                                                                                           ` Ilias Apalodimas
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-08-02 13:41 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, nd, u-boot, jens.wiklander

Hi Ilias,

On Wed, 2 Aug 2023 at 07:38, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Simon,
>
> On Wed, 2 Aug 2023 at 16:34, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Ilias,
> >
> > On Wed, 2 Aug 2023 at 07:27, Ilias Apalodimas
> > <ilias.apalodimas@linaro.org> wrote:
> > >
> > > Hi Simon,
> > >
> > >
> > > On Wed, 2 Aug 2023 at 16:09, Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Ilias,
> > > >
> > > > On Wed, 2 Aug 2023 at 07:02, Ilias Apalodimas
> > > > <ilias.apalodimas@linaro.org> wrote:
> > > > >
> > > > > Hi Simon,
> > > > >
> > > > > On Wed, 2 Aug 2023 at 15:52, Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > Hi Ilias,
> > > > > >
> > > > > > On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
> > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > >
> > > > > > > On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> > > > > > > >
> > > > > > > > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > > > > > > > Hi guys,
> > > > > > > > >
> > > > > > > > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > > > > > > > ...
> > > > > > > > > > > > > > > > > Changelog:
> > > > > > > > > > > > > > > > > ===============
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > v17:
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > > > > > > > [snip]
> > > > > > > > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > > > > > > > platform.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > > Since FF-A isn't a new
> > > > > > > > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > > > > > > > easier.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > > > > > > > here.
> > > > > > > > > > > > > >
> > > > > > > > > > > > >
> > > > > > > > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > > > > > > > >
> > > > > > > > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > > > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > > > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > > > > > > > >
> > > > > > > > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > > > > > > > addresses show up is as confusing as having Kconfig options for
> > > > > > > > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > > > > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > > > > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > > > > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > > > > > > > >
> > > > > > > > > > > Tom you prefer that as well?
> > > > > > > > > >
> > > > > > > > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > > > > > > > fine, especially since default values of 0 are nonsense in this case
> > > > > > > > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > > > > > > > 0x0 once we do string comparisons).
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > > I'd like to give some context why it's important for Corstone-1000 platform
> > > > > > > > > that the DT passed to the kernel matches the official kernel DT.
> > > > > > > >
> > > > > > > > Note that we've set aside the "should this be in DT or not" question.
> > > > > > > >
> > > > > > > > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > > > > > > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > > > > > > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > > > > > > > to the kernel DT, the DT test will fail.
> > > > > > > >
> > > > > > > > This is overall good and progress.
> > > > > > > >
> > > > > > > > > To be approved by the kernel DT maintainers, the node should have a use case
> > > > > > > > > in the kernel which is not the case.
> > > > > > > >
> > > > > > > > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > > > > > > > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > > > > > > > are in dt-schema and so can be in the upstream kernel but are not used
> > > > > > > > in the kernel itself.
> > > > > > > >
> > > > > > > > > There is a solution for this which is deleting the node we don't want to pass to
> > > > > > > > > the kernel using delete-node in the U-Boot DT.
> > > > > > > >
> > > > > > > > Something like this will likely be needed, in the end, at least for some
> > > > > > > > cases.  But the goal is that everything gets in to dt-schema.
> > > > > > >
> > > > > > > We are already working on U-Boot on that.  The idea is rather simple.
> > > > > > > We will have an array with nodes and node entries.  Before we boot up
> > > > > > > we'll scan that array, if a node entry exists we will delete that,
> > > > > > > otherwise we will just get rid of the entire node.  That should be
> > > > > > > pretty easy to maintain and extend.  U-Boot will then be able to use
> > > > > > > it;s internal bidings without polluting the DT we handover to the
> > > > > > > kernel.
> > > > > >
> > > > > > This is not pollution - we have moved past that now and Linux has
> > > > > > accepted some U-Boot bindings. This is the DT and if there are things
> > > > > > in it that are not related to Linux, it can ignore them.
> > > > > >
> > > > > > We should add whatever bindings we need to make U-Boot work
> > > > > > efficiently and correctly.
> > > > > >
> > > > >
> > > > > The cases that are already accepted make sense.  Things like the
> > > > > public part of the certificates used to authenticate capsule updates
> > > > > or the encoding of the recent a/b update nodes are not needed in any
> > > > > way in an OS.  Those don't make sense to upstream and those are
> > > > > polluting the DT and need stripping
> > > >
> > > > It doesn't matter that Linux doesn't *need* it. If it is there it will
> > > > have to accommodate it. We have loads of Linux stuff in the DT that
> > > > means nothing to U-Boot. Many of the bindings chosen by Linux are
> > > > wildly inefficient for U-Boot to implement.
> > > >
> > > > We don't need to strip anything. This is not pollution. It is a
> > > > binding agreement between projects.
> > > >
> > >
> > > I am not a maintainer, but I doubt they view it that way.  In any
> >
> > Who?
> >
> > > case, the DT produced by u-boot fails to pass the certification on
> >
> > U-Boot
> >
> > > every single platform that uses nonupstream nodes, so cleaning that up
> > > is needed.  If people care enough and upstream those bindings we can
> > > preserve them
> >
> > Yes I agree, and the bindings that are added need to be upstream in
> > dt-schema. This applies also to the work that Linaro does.
> >
> > I will mention this to Sugosh as well as he is adding a public key.
>
> He is already aware, he is working on a PoC that does exactly what I
> described.  Once we verify devices are starting to pass the
> SystemReady2.0 certification he will send an RFC

What PoC? You mean bindings?

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02 13:41                                                                                                                                                                                         ` Simon Glass
@ 2023-08-02 13:42                                                                                                                                                                                           ` Ilias Apalodimas
  2023-08-02 13:44                                                                                                                                                                                             ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-08-02 13:42 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, nd, u-boot, jens.wiklander

On Wed, 2 Aug 2023 at 16:42, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Ilias,
>
> On Wed, 2 Aug 2023 at 07:38, Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > Hi Simon,
> >
> > On Wed, 2 Aug 2023 at 16:34, Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Ilias,
> > >
> > > On Wed, 2 Aug 2023 at 07:27, Ilias Apalodimas
> > > <ilias.apalodimas@linaro.org> wrote:
> > > >
> > > > Hi Simon,
> > > >
> > > >
> > > > On Wed, 2 Aug 2023 at 16:09, Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > Hi Ilias,
> > > > >
> > > > > On Wed, 2 Aug 2023 at 07:02, Ilias Apalodimas
> > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > >
> > > > > > Hi Simon,
> > > > > >
> > > > > > On Wed, 2 Aug 2023 at 15:52, Simon Glass <sjg@chromium.org> wrote:
> > > > > > >
> > > > > > > Hi Ilias,
> > > > > > >
> > > > > > > On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
> > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > >
> > > > > > > > On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> > > > > > > > >
> > > > > > > > > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > > > > > > > > Hi guys,
> > > > > > > > > >
> > > > > > > > > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > > > > > > > > ...
> > > > > > > > > > > > > > > > > > Changelog:
> > > > > > > > > > > > > > > > > > ===============
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > v17:
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > > > > > > > > [snip]
> > > > > > > > > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > > > > > > > > platform.
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > Since FF-A isn't a new
> > > > > > > > > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > > > > > > > > easier.
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > > > > > > > > here.
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > > > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > > > > > > > > >
> > > > > > > > > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > > > > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > > > > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > > > > > > > > >
> > > > > > > > > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > > > > > > > > addresses show up is as confusing as having Kconfig options for
> > > > > > > > > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > > > > > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > > > > > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > > > > > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > > > > > > > > >
> > > > > > > > > > > > Tom you prefer that as well?
> > > > > > > > > > >
> > > > > > > > > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > > > > > > > > fine, especially since default values of 0 are nonsense in this case
> > > > > > > > > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > > > > > > > > 0x0 once we do string comparisons).
> > > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > I'd like to give some context why it's important for Corstone-1000 platform
> > > > > > > > > > that the DT passed to the kernel matches the official kernel DT.
> > > > > > > > >
> > > > > > > > > Note that we've set aside the "should this be in DT or not" question.
> > > > > > > > >
> > > > > > > > > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > > > > > > > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > > > > > > > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > > > > > > > > to the kernel DT, the DT test will fail.
> > > > > > > > >
> > > > > > > > > This is overall good and progress.
> > > > > > > > >
> > > > > > > > > > To be approved by the kernel DT maintainers, the node should have a use case
> > > > > > > > > > in the kernel which is not the case.
> > > > > > > > >
> > > > > > > > > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > > > > > > > > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > > > > > > > > are in dt-schema and so can be in the upstream kernel but are not used
> > > > > > > > > in the kernel itself.
> > > > > > > > >
> > > > > > > > > > There is a solution for this which is deleting the node we don't want to pass to
> > > > > > > > > > the kernel using delete-node in the U-Boot DT.
> > > > > > > > >
> > > > > > > > > Something like this will likely be needed, in the end, at least for some
> > > > > > > > > cases.  But the goal is that everything gets in to dt-schema.
> > > > > > > >
> > > > > > > > We are already working on U-Boot on that.  The idea is rather simple.
> > > > > > > > We will have an array with nodes and node entries.  Before we boot up
> > > > > > > > we'll scan that array, if a node entry exists we will delete that,
> > > > > > > > otherwise we will just get rid of the entire node.  That should be
> > > > > > > > pretty easy to maintain and extend.  U-Boot will then be able to use
> > > > > > > > it;s internal bidings without polluting the DT we handover to the
> > > > > > > > kernel.
> > > > > > >
> > > > > > > This is not pollution - we have moved past that now and Linux has
> > > > > > > accepted some U-Boot bindings. This is the DT and if there are things
> > > > > > > in it that are not related to Linux, it can ignore them.
> > > > > > >
> > > > > > > We should add whatever bindings we need to make U-Boot work
> > > > > > > efficiently and correctly.
> > > > > > >
> > > > > >
> > > > > > The cases that are already accepted make sense.  Things like the
> > > > > > public part of the certificates used to authenticate capsule updates
> > > > > > or the encoding of the recent a/b update nodes are not needed in any
> > > > > > way in an OS.  Those don't make sense to upstream and those are
> > > > > > polluting the DT and need stripping
> > > > >
> > > > > It doesn't matter that Linux doesn't *need* it. If it is there it will
> > > > > have to accommodate it. We have loads of Linux stuff in the DT that
> > > > > means nothing to U-Boot. Many of the bindings chosen by Linux are
> > > > > wildly inefficient for U-Boot to implement.
> > > > >
> > > > > We don't need to strip anything. This is not pollution. It is a
> > > > > binding agreement between projects.
> > > > >
> > > >
> > > > I am not a maintainer, but I doubt they view it that way.  In any
> > >
> > > Who?
> > >
> > > > case, the DT produced by u-boot fails to pass the certification on
> > >
> > > U-Boot
> > >
> > > > every single platform that uses nonupstream nodes, so cleaning that up
> > > > is needed.  If people care enough and upstream those bindings we can
> > > > preserve them
> > >
> > > Yes I agree, and the bindings that are added need to be upstream in
> > > dt-schema. This applies also to the work that Linaro does.
> > >
> > > I will mention this to Sugosh as well as he is adding a public key.
> >
> > He is already aware, he is working on a PoC that does exactly what I
> > described.  Once we verify devices are starting to pass the
> > SystemReady2.0 certification he will send an RFC
>
> What PoC? You mean bindings?

stripping of bindings that are not upstreamed in  the dt-schema


>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02 13:42                                                                                                                                                                                           ` Ilias Apalodimas
@ 2023-08-02 13:44                                                                                                                                                                                             ` Simon Glass
  2023-08-02 13:47                                                                                                                                                                                               ` Ilias Apalodimas
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-08-02 13:44 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, nd, u-boot, jens.wiklander

Hi Ilias,

On Wed, 2 Aug 2023 at 07:43, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> On Wed, 2 Aug 2023 at 16:42, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Ilias,
> >
> > On Wed, 2 Aug 2023 at 07:38, Ilias Apalodimas
> > <ilias.apalodimas@linaro.org> wrote:
> > >
> > > Hi Simon,
> > >
> > > On Wed, 2 Aug 2023 at 16:34, Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Ilias,
> > > >
> > > > On Wed, 2 Aug 2023 at 07:27, Ilias Apalodimas
> > > > <ilias.apalodimas@linaro.org> wrote:
> > > > >
> > > > > Hi Simon,
> > > > >
> > > > >
> > > > > On Wed, 2 Aug 2023 at 16:09, Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > Hi Ilias,
> > > > > >
> > > > > > On Wed, 2 Aug 2023 at 07:02, Ilias Apalodimas
> > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > >
> > > > > > > Hi Simon,
> > > > > > >
> > > > > > > On Wed, 2 Aug 2023 at 15:52, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > >
> > > > > > > > Hi Ilias,
> > > > > > > >
> > > > > > > > On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
> > > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > > >
> > > > > > > > > On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> > > > > > > > > >
> > > > > > > > > > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > > > > > > > > > Hi guys,
> > > > > > > > > > >
> > > > > > > > > > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > > > > > > > > > ...
> > > > > > > > > > > > > > > > > > > Changelog:
> > > > > > > > > > > > > > > > > > > ===============
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > v17:
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > > > > > > > > > [snip]
> > > > > > > > > > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > > > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > > > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > > > > > > > > > platform.
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > Since FF-A isn't a new
> > > > > > > > > > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > > > > > > > > > easier.
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > > > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > > > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > > > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > > > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > > > > > > > > > here.
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > > > > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > > > > > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > > > > > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > > > > > > > > > addresses show up is as confusing as having Kconfig options for
> > > > > > > > > > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > > > > > > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > > > > > > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > > > > > > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Tom you prefer that as well?
> > > > > > > > > > > >
> > > > > > > > > > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > > > > > > > > > fine, especially since default values of 0 are nonsense in this case
> > > > > > > > > > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > > > > > > > > > 0x0 once we do string comparisons).
> > > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > I'd like to give some context why it's important for Corstone-1000 platform
> > > > > > > > > > > that the DT passed to the kernel matches the official kernel DT.
> > > > > > > > > >
> > > > > > > > > > Note that we've set aside the "should this be in DT or not" question.
> > > > > > > > > >
> > > > > > > > > > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > > > > > > > > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > > > > > > > > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > > > > > > > > > to the kernel DT, the DT test will fail.
> > > > > > > > > >
> > > > > > > > > > This is overall good and progress.
> > > > > > > > > >
> > > > > > > > > > > To be approved by the kernel DT maintainers, the node should have a use case
> > > > > > > > > > > in the kernel which is not the case.
> > > > > > > > > >
> > > > > > > > > > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > > > > > > > > > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > > > > > > > > > are in dt-schema and so can be in the upstream kernel but are not used
> > > > > > > > > > in the kernel itself.
> > > > > > > > > >
> > > > > > > > > > > There is a solution for this which is deleting the node we don't want to pass to
> > > > > > > > > > > the kernel using delete-node in the U-Boot DT.
> > > > > > > > > >
> > > > > > > > > > Something like this will likely be needed, in the end, at least for some
> > > > > > > > > > cases.  But the goal is that everything gets in to dt-schema.
> > > > > > > > >
> > > > > > > > > We are already working on U-Boot on that.  The idea is rather simple.
> > > > > > > > > We will have an array with nodes and node entries.  Before we boot up
> > > > > > > > > we'll scan that array, if a node entry exists we will delete that,
> > > > > > > > > otherwise we will just get rid of the entire node.  That should be
> > > > > > > > > pretty easy to maintain and extend.  U-Boot will then be able to use
> > > > > > > > > it;s internal bidings without polluting the DT we handover to the
> > > > > > > > > kernel.
> > > > > > > >
> > > > > > > > This is not pollution - we have moved past that now and Linux has
> > > > > > > > accepted some U-Boot bindings. This is the DT and if there are things
> > > > > > > > in it that are not related to Linux, it can ignore them.
> > > > > > > >
> > > > > > > > We should add whatever bindings we need to make U-Boot work
> > > > > > > > efficiently and correctly.
> > > > > > > >
> > > > > > >
> > > > > > > The cases that are already accepted make sense.  Things like the
> > > > > > > public part of the certificates used to authenticate capsule updates
> > > > > > > or the encoding of the recent a/b update nodes are not needed in any
> > > > > > > way in an OS.  Those don't make sense to upstream and those are
> > > > > > > polluting the DT and need stripping
> > > > > >
> > > > > > It doesn't matter that Linux doesn't *need* it. If it is there it will
> > > > > > have to accommodate it. We have loads of Linux stuff in the DT that
> > > > > > means nothing to U-Boot. Many of the bindings chosen by Linux are
> > > > > > wildly inefficient for U-Boot to implement.
> > > > > >
> > > > > > We don't need to strip anything. This is not pollution. It is a
> > > > > > binding agreement between projects.
> > > > > >
> > > > >
> > > > > I am not a maintainer, but I doubt they view it that way.  In any
> > > >
> > > > Who?
> > > >
> > > > > case, the DT produced by u-boot fails to pass the certification on
> > > >
> > > > U-Boot
> > > >
> > > > > every single platform that uses nonupstream nodes, so cleaning that up
> > > > > is needed.  If people care enough and upstream those bindings we can
> > > > > preserve them
> > > >
> > > > Yes I agree, and the bindings that are added need to be upstream in
> > > > dt-schema. This applies also to the work that Linaro does.
> > > >
> > > > I will mention this to Sugosh as well as he is adding a public key.
> > >
> > > He is already aware, he is working on a PoC that does exactly what I
> > > described.  Once we verify devices are starting to pass the
> > > SystemReady2.0 certification he will send an RFC
> >
> > What PoC? You mean bindings?
>
> stripping of bindings that are not upstreamed in  the dt-schema

If that is what you want to do, then the binding needs to go upstream
before we accept his patches.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02 13:44                                                                                                                                                                                             ` Simon Glass
@ 2023-08-02 13:47                                                                                                                                                                                               ` Ilias Apalodimas
  2023-08-02 13:55                                                                                                                                                                                                 ` Simon Glass
  0 siblings, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-08-02 13:47 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, nd, u-boot, jens.wiklander

Hi Simon,

On Wed, 2 Aug 2023 at 16:44, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Ilias,
>
> On Wed, 2 Aug 2023 at 07:43, Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > On Wed, 2 Aug 2023 at 16:42, Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Ilias,
> > >
> > > On Wed, 2 Aug 2023 at 07:38, Ilias Apalodimas
> > > <ilias.apalodimas@linaro.org> wrote:
> > > >
> > > > Hi Simon,
> > > >
> > > > On Wed, 2 Aug 2023 at 16:34, Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > Hi Ilias,
> > > > >
> > > > > On Wed, 2 Aug 2023 at 07:27, Ilias Apalodimas
> > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > >
> > > > > > Hi Simon,
> > > > > >
> > > > > >
> > > > > > On Wed, 2 Aug 2023 at 16:09, Simon Glass <sjg@chromium.org> wrote:
> > > > > > >
> > > > > > > Hi Ilias,
> > > > > > >
> > > > > > > On Wed, 2 Aug 2023 at 07:02, Ilias Apalodimas
> > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > >
> > > > > > > > Hi Simon,
> > > > > > > >
> > > > > > > > On Wed, 2 Aug 2023 at 15:52, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > >
> > > > > > > > > Hi Ilias,
> > > > > > > > >
> > > > > > > > > On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
> > > > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > > > >
> > > > > > > > > > On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> > > > > > > > > > >
> > > > > > > > > > > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > > > > > > > > > > Hi guys,
> > > > > > > > > > > >
> > > > > > > > > > > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > > > > > > > > > > ...
> > > > > > > > > > > > > > > > > > > > Changelog:
> > > > > > > > > > > > > > > > > > > > ===============
> > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > v17:
> > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > > > > > > > > > > [snip]
> > > > > > > > > > > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > > > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > > > > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > > > > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > > > > > > > > > > platform.
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > Since FF-A isn't a new
> > > > > > > > > > > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > > > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > > > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > > > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > > > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > > > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > > > > > > > > > > easier.
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > > > > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > > > > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > > > > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > > > > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > > > > > > > > > > here.
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > > > > > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > > > > > > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > > > > > > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > > > > > > > > > > addresses show up is as confusing as having Kconfig options for
> > > > > > > > > > > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > > > > > > > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > > > > > > > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > > > > > > > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > Tom you prefer that as well?
> > > > > > > > > > > > >
> > > > > > > > > > > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > > > > > > > > > > fine, especially since default values of 0 are nonsense in this case
> > > > > > > > > > > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > > > > > > > > > > 0x0 once we do string comparisons).
> > > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > > I'd like to give some context why it's important for Corstone-1000 platform
> > > > > > > > > > > > that the DT passed to the kernel matches the official kernel DT.
> > > > > > > > > > >
> > > > > > > > > > > Note that we've set aside the "should this be in DT or not" question.
> > > > > > > > > > >
> > > > > > > > > > > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > > > > > > > > > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > > > > > > > > > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > > > > > > > > > > to the kernel DT, the DT test will fail.
> > > > > > > > > > >
> > > > > > > > > > > This is overall good and progress.
> > > > > > > > > > >
> > > > > > > > > > > > To be approved by the kernel DT maintainers, the node should have a use case
> > > > > > > > > > > > in the kernel which is not the case.
> > > > > > > > > > >
> > > > > > > > > > > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > > > > > > > > > > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > > > > > > > > > > are in dt-schema and so can be in the upstream kernel but are not used
> > > > > > > > > > > in the kernel itself.
> > > > > > > > > > >
> > > > > > > > > > > > There is a solution for this which is deleting the node we don't want to pass to
> > > > > > > > > > > > the kernel using delete-node in the U-Boot DT.
> > > > > > > > > > >
> > > > > > > > > > > Something like this will likely be needed, in the end, at least for some
> > > > > > > > > > > cases.  But the goal is that everything gets in to dt-schema.
> > > > > > > > > >
> > > > > > > > > > We are already working on U-Boot on that.  The idea is rather simple.
> > > > > > > > > > We will have an array with nodes and node entries.  Before we boot up
> > > > > > > > > > we'll scan that array, if a node entry exists we will delete that,
> > > > > > > > > > otherwise we will just get rid of the entire node.  That should be
> > > > > > > > > > pretty easy to maintain and extend.  U-Boot will then be able to use
> > > > > > > > > > it;s internal bidings without polluting the DT we handover to the
> > > > > > > > > > kernel.
> > > > > > > > >
> > > > > > > > > This is not pollution - we have moved past that now and Linux has
> > > > > > > > > accepted some U-Boot bindings. This is the DT and if there are things
> > > > > > > > > in it that are not related to Linux, it can ignore them.
> > > > > > > > >
> > > > > > > > > We should add whatever bindings we need to make U-Boot work
> > > > > > > > > efficiently and correctly.
> > > > > > > > >
> > > > > > > >
> > > > > > > > The cases that are already accepted make sense.  Things like the
> > > > > > > > public part of the certificates used to authenticate capsule updates
> > > > > > > > or the encoding of the recent a/b update nodes are not needed in any
> > > > > > > > way in an OS.  Those don't make sense to upstream and those are
> > > > > > > > polluting the DT and need stripping
> > > > > > >
> > > > > > > It doesn't matter that Linux doesn't *need* it. If it is there it will
> > > > > > > have to accommodate it. We have loads of Linux stuff in the DT that
> > > > > > > means nothing to U-Boot. Many of the bindings chosen by Linux are
> > > > > > > wildly inefficient for U-Boot to implement.
> > > > > > >
> > > > > > > We don't need to strip anything. This is not pollution. It is a
> > > > > > > binding agreement between projects.
> > > > > > >
> > > > > >
> > > > > > I am not a maintainer, but I doubt they view it that way.  In any
> > > > >
> > > > > Who?
> > > > >
> > > > > > case, the DT produced by u-boot fails to pass the certification on
> > > > >
> > > > > U-Boot
> > > > >
> > > > > > every single platform that uses nonupstream nodes, so cleaning that up
> > > > > > is needed.  If people care enough and upstream those bindings we can
> > > > > > preserve them
> > > > >
> > > > > Yes I agree, and the bindings that are added need to be upstream in
> > > > > dt-schema. This applies also to the work that Linaro does.
> > > > >
> > > > > I will mention this to Sugosh as well as he is adding a public key.
> > > >
> > > > He is already aware, he is working on a PoC that does exactly what I
> > > > described.  Once we verify devices are starting to pass the
> > > > SystemReady2.0 certification he will send an RFC
> > >
> > > What PoC? You mean bindings?
> >
> > stripping of bindings that are not upstreamed in  the dt-schema
>
> If that is what you want to do, then the binding needs to go upstream
> before we accept his patches.

This makes no sense whatsoever.  Sughosh isn't adding anything new.
Having the public portion on the DT file is something you insisted
upon years ago and even reverted patches from me that had the key as a
Kconfig option (which notably suffered from non of these problems, or
the increased complexity we are adding now).  What Sughosh is adding
is autogenerating that, instead of having to manually stitch the DT.

Thanks
/Ilias
>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02 13:47                                                                                                                                                                                               ` Ilias Apalodimas
@ 2023-08-02 13:55                                                                                                                                                                                                 ` Simon Glass
  2023-08-02 13:59                                                                                                                                                                                                   ` Ilias Apalodimas
  2023-08-02 15:38                                                                                                                                                                                                   ` Tom Rini
  0 siblings, 2 replies; 478+ messages in thread
From: Simon Glass @ 2023-08-02 13:55 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, nd, u-boot, jens.wiklander

Hi Ilias,

On Wed, 2 Aug 2023 at 07:48, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Simon,
>
> On Wed, 2 Aug 2023 at 16:44, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Ilias,
> >
> > On Wed, 2 Aug 2023 at 07:43, Ilias Apalodimas
> > <ilias.apalodimas@linaro.org> wrote:
> > >
> > > On Wed, 2 Aug 2023 at 16:42, Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Ilias,
> > > >
> > > > On Wed, 2 Aug 2023 at 07:38, Ilias Apalodimas
> > > > <ilias.apalodimas@linaro.org> wrote:
> > > > >
> > > > > Hi Simon,
> > > > >
> > > > > On Wed, 2 Aug 2023 at 16:34, Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > Hi Ilias,
> > > > > >
> > > > > > On Wed, 2 Aug 2023 at 07:27, Ilias Apalodimas
> > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > >
> > > > > > > Hi Simon,
> > > > > > >
> > > > > > >
> > > > > > > On Wed, 2 Aug 2023 at 16:09, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > >
> > > > > > > > Hi Ilias,
> > > > > > > >
> > > > > > > > On Wed, 2 Aug 2023 at 07:02, Ilias Apalodimas
> > > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > > >
> > > > > > > > > Hi Simon,
> > > > > > > > >
> > > > > > > > > On Wed, 2 Aug 2023 at 15:52, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > > >
> > > > > > > > > > Hi Ilias,
> > > > > > > > > >
> > > > > > > > > > On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
> > > > > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > > > > >
> > > > > > > > > > > On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > > > > > > > > > > > Hi guys,
> > > > > > > > > > > > >
> > > > > > > > > > > > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > > > > > > > > > > > ...
> > > > > > > > > > > > > > > > > > > > > Changelog:
> > > > > > > > > > > > > > > > > > > > > ===============
> > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > v17:
> > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > > > > > > > > > > > [snip]
> > > > > > > > > > > > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > > > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > > > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > > > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > > > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > > > > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > > > > > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > > > > > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > > > > > > > > > > > platform.
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > Since FF-A isn't a new
> > > > > > > > > > > > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > > > > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > > > > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > > > > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > > > > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > > > > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > > > > > > > > > > > easier.
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > > > > > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > > > > > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > > > > > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > > > > > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > > > > > > > > > > > here.
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > > > > > > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > > > > > > > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > > > > > > > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > > > > > > > > > > > addresses show up is as confusing as having Kconfig options for
> > > > > > > > > > > > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > > > > > > > > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > > > > > > > > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > > > > > > > > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > Tom you prefer that as well?
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > > > > > > > > > > > fine, especially since default values of 0 are nonsense in this case
> > > > > > > > > > > > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > > > > > > > > > > > 0x0 once we do string comparisons).
> > > > > > > > > > > > > >
> > > > > > > > > > > > >
> > > > > > > > > > > > > I'd like to give some context why it's important for Corstone-1000 platform
> > > > > > > > > > > > > that the DT passed to the kernel matches the official kernel DT.
> > > > > > > > > > > >
> > > > > > > > > > > > Note that we've set aside the "should this be in DT or not" question.
> > > > > > > > > > > >
> > > > > > > > > > > > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > > > > > > > > > > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > > > > > > > > > > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > > > > > > > > > > > to the kernel DT, the DT test will fail.
> > > > > > > > > > > >
> > > > > > > > > > > > This is overall good and progress.
> > > > > > > > > > > >
> > > > > > > > > > > > > To be approved by the kernel DT maintainers, the node should have a use case
> > > > > > > > > > > > > in the kernel which is not the case.
> > > > > > > > > > > >
> > > > > > > > > > > > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > > > > > > > > > > > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > > > > > > > > > > > are in dt-schema and so can be in the upstream kernel but are not used
> > > > > > > > > > > > in the kernel itself.
> > > > > > > > > > > >
> > > > > > > > > > > > > There is a solution for this which is deleting the node we don't want to pass to
> > > > > > > > > > > > > the kernel using delete-node in the U-Boot DT.
> > > > > > > > > > > >
> > > > > > > > > > > > Something like this will likely be needed, in the end, at least for some
> > > > > > > > > > > > cases.  But the goal is that everything gets in to dt-schema.
> > > > > > > > > > >
> > > > > > > > > > > We are already working on U-Boot on that.  The idea is rather simple.
> > > > > > > > > > > We will have an array with nodes and node entries.  Before we boot up
> > > > > > > > > > > we'll scan that array, if a node entry exists we will delete that,
> > > > > > > > > > > otherwise we will just get rid of the entire node.  That should be
> > > > > > > > > > > pretty easy to maintain and extend.  U-Boot will then be able to use
> > > > > > > > > > > it;s internal bidings without polluting the DT we handover to the
> > > > > > > > > > > kernel.
> > > > > > > > > >
> > > > > > > > > > This is not pollution - we have moved past that now and Linux has
> > > > > > > > > > accepted some U-Boot bindings. This is the DT and if there are things
> > > > > > > > > > in it that are not related to Linux, it can ignore them.
> > > > > > > > > >
> > > > > > > > > > We should add whatever bindings we need to make U-Boot work
> > > > > > > > > > efficiently and correctly.
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > > The cases that are already accepted make sense.  Things like the
> > > > > > > > > public part of the certificates used to authenticate capsule updates
> > > > > > > > > or the encoding of the recent a/b update nodes are not needed in any
> > > > > > > > > way in an OS.  Those don't make sense to upstream and those are
> > > > > > > > > polluting the DT and need stripping
> > > > > > > >
> > > > > > > > It doesn't matter that Linux doesn't *need* it. If it is there it will
> > > > > > > > have to accommodate it. We have loads of Linux stuff in the DT that
> > > > > > > > means nothing to U-Boot. Many of the bindings chosen by Linux are
> > > > > > > > wildly inefficient for U-Boot to implement.
> > > > > > > >
> > > > > > > > We don't need to strip anything. This is not pollution. It is a
> > > > > > > > binding agreement between projects.
> > > > > > > >
> > > > > > >
> > > > > > > I am not a maintainer, but I doubt they view it that way.  In any
> > > > > >
> > > > > > Who?
> > > > > >
> > > > > > > case, the DT produced by u-boot fails to pass the certification on
> > > > > >
> > > > > > U-Boot
> > > > > >
> > > > > > > every single platform that uses nonupstream nodes, so cleaning that up
> > > > > > > is needed.  If people care enough and upstream those bindings we can
> > > > > > > preserve them
> > > > > >
> > > > > > Yes I agree, and the bindings that are added need to be upstream in
> > > > > > dt-schema. This applies also to the work that Linaro does.
> > > > > >
> > > > > > I will mention this to Sugosh as well as he is adding a public key.
> > > > >
> > > > > He is already aware, he is working on a PoC that does exactly what I
> > > > > described.  Once we verify devices are starting to pass the
> > > > > SystemReady2.0 certification he will send an RFC
> > > >
> > > > What PoC? You mean bindings?
> > >
> > > stripping of bindings that are not upstreamed in  the dt-schema
> >
> > If that is what you want to do, then the binding needs to go upstream
> > before we accept his patches.
>
> This makes no sense whatsoever.  Sughosh isn't adding anything new.
> Having the public portion on the DT file is something you insisted
> upon years ago and even reverted patches from me that had the key as a
> Kconfig option (which notably suffered from non of these problems, or
> the increased complexity we are adding now).  What Sughosh is adding
> is autogenerating that, instead of having to manually stitch the DT.

Yes and it forms part of the machine's DT and needs to have a binding,
just like the Binman nodes need a binding. Isn't this the whole point?

Either:
- we upstream the U-Boot bindings, or
- we allow U-Boot to put whatever it wants in there and accept it

I much prefer the first option since we can run validation on it, as
I'm sure you would prefer. But removing nodes before booting just
because we haven't upstreamed things is just going to lead to no one
bothering to do it.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02 13:55                                                                                                                                                                                                 ` Simon Glass
@ 2023-08-02 13:59                                                                                                                                                                                                   ` Ilias Apalodimas
  2023-08-02 16:10                                                                                                                                                                                                     ` Simon Glass
  2023-08-02 15:38                                                                                                                                                                                                   ` Tom Rini
  1 sibling, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-08-02 13:59 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, nd, u-boot, jens.wiklander

Hi Simon,

On Wed, 2 Aug 2023 at 16:55, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Ilias,
>
> On Wed, 2 Aug 2023 at 07:48, Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > Hi Simon,
> >
> > On Wed, 2 Aug 2023 at 16:44, Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Ilias,
> > >
> > > On Wed, 2 Aug 2023 at 07:43, Ilias Apalodimas
> > > <ilias.apalodimas@linaro.org> wrote:
> > > >
> > > > On Wed, 2 Aug 2023 at 16:42, Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > Hi Ilias,
> > > > >
> > > > > On Wed, 2 Aug 2023 at 07:38, Ilias Apalodimas
> > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > >
> > > > > > Hi Simon,
> > > > > >
> > > > > > On Wed, 2 Aug 2023 at 16:34, Simon Glass <sjg@chromium.org> wrote:
> > > > > > >
> > > > > > > Hi Ilias,
> > > > > > >
> > > > > > > On Wed, 2 Aug 2023 at 07:27, Ilias Apalodimas
> > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > >
> > > > > > > > Hi Simon,
> > > > > > > >
> > > > > > > >
> > > > > > > > On Wed, 2 Aug 2023 at 16:09, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > >
> > > > > > > > > Hi Ilias,
> > > > > > > > >
> > > > > > > > > On Wed, 2 Aug 2023 at 07:02, Ilias Apalodimas
> > > > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > > > >
> > > > > > > > > > Hi Simon,
> > > > > > > > > >
> > > > > > > > > > On Wed, 2 Aug 2023 at 15:52, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > > > >
> > > > > > > > > > > Hi Ilias,
> > > > > > > > > > >
> > > > > > > > > > > On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
> > > > > > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> > > > > > > > > > > > >
> > > > > > > > > > > > > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > > > > > > > > > > > > Hi guys,
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > > > > > > > > > > > > ...
> > > > > > > > > > > > > > > > > > > > > > Changelog:
> > > > > > > > > > > > > > > > > > > > > > ===============
> > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > v17:
> > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > > > > > > > > > > > > [snip]
> > > > > > > > > > > > > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > > > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > > > > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > > > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > > > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > > > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > > > > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > > > > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > > > > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > > > > > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > > > > > > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > > > > > > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > > > > > > > > > > > > platform.
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > Since FF-A isn't a new
> > > > > > > > > > > > > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > > > > > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > > > > > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > > > > > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > > > > > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > > > > > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > > > > > > > > > > > > easier.
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > > > > > > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > > > > > > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > > > > > > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > > > > > > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > > > > > > > > > > > > here.
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > > > > > > > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > > > > > > > > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > > > > > > > > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > > > > > > > > > > > > addresses show up is as confusing as having Kconfig options for
> > > > > > > > > > > > > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > > > > > > > > > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > > > > > > > > > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > > > > > > > > > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > Tom you prefer that as well?
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > > > > > > > > > > > > fine, especially since default values of 0 are nonsense in this case
> > > > > > > > > > > > > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > > > > > > > > > > > > 0x0 once we do string comparisons).
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > I'd like to give some context why it's important for Corstone-1000 platform
> > > > > > > > > > > > > > that the DT passed to the kernel matches the official kernel DT.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Note that we've set aside the "should this be in DT or not" question.
> > > > > > > > > > > > >
> > > > > > > > > > > > > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > > > > > > > > > > > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > > > > > > > > > > > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > > > > > > > > > > > > to the kernel DT, the DT test will fail.
> > > > > > > > > > > > >
> > > > > > > > > > > > > This is overall good and progress.
> > > > > > > > > > > > >
> > > > > > > > > > > > > > To be approved by the kernel DT maintainers, the node should have a use case
> > > > > > > > > > > > > > in the kernel which is not the case.
> > > > > > > > > > > > >
> > > > > > > > > > > > > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > > > > > > > > > > > > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > > > > > > > > > > > > are in dt-schema and so can be in the upstream kernel but are not used
> > > > > > > > > > > > > in the kernel itself.
> > > > > > > > > > > > >
> > > > > > > > > > > > > > There is a solution for this which is deleting the node we don't want to pass to
> > > > > > > > > > > > > > the kernel using delete-node in the U-Boot DT.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Something like this will likely be needed, in the end, at least for some
> > > > > > > > > > > > > cases.  But the goal is that everything gets in to dt-schema.
> > > > > > > > > > > >
> > > > > > > > > > > > We are already working on U-Boot on that.  The idea is rather simple.
> > > > > > > > > > > > We will have an array with nodes and node entries.  Before we boot up
> > > > > > > > > > > > we'll scan that array, if a node entry exists we will delete that,
> > > > > > > > > > > > otherwise we will just get rid of the entire node.  That should be
> > > > > > > > > > > > pretty easy to maintain and extend.  U-Boot will then be able to use
> > > > > > > > > > > > it;s internal bidings without polluting the DT we handover to the
> > > > > > > > > > > > kernel.
> > > > > > > > > > >
> > > > > > > > > > > This is not pollution - we have moved past that now and Linux has
> > > > > > > > > > > accepted some U-Boot bindings. This is the DT and if there are things
> > > > > > > > > > > in it that are not related to Linux, it can ignore them.
> > > > > > > > > > >
> > > > > > > > > > > We should add whatever bindings we need to make U-Boot work
> > > > > > > > > > > efficiently and correctly.
> > > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > The cases that are already accepted make sense.  Things like the
> > > > > > > > > > public part of the certificates used to authenticate capsule updates
> > > > > > > > > > or the encoding of the recent a/b update nodes are not needed in any
> > > > > > > > > > way in an OS.  Those don't make sense to upstream and those are
> > > > > > > > > > polluting the DT and need stripping
> > > > > > > > >
> > > > > > > > > It doesn't matter that Linux doesn't *need* it. If it is there it will
> > > > > > > > > have to accommodate it. We have loads of Linux stuff in the DT that
> > > > > > > > > means nothing to U-Boot. Many of the bindings chosen by Linux are
> > > > > > > > > wildly inefficient for U-Boot to implement.
> > > > > > > > >
> > > > > > > > > We don't need to strip anything. This is not pollution. It is a
> > > > > > > > > binding agreement between projects.
> > > > > > > > >
> > > > > > > >
> > > > > > > > I am not a maintainer, but I doubt they view it that way.  In any
> > > > > > >
> > > > > > > Who?
> > > > > > >
> > > > > > > > case, the DT produced by u-boot fails to pass the certification on
> > > > > > >
> > > > > > > U-Boot
> > > > > > >
> > > > > > > > every single platform that uses nonupstream nodes, so cleaning that up
> > > > > > > > is needed.  If people care enough and upstream those bindings we can
> > > > > > > > preserve them
> > > > > > >
> > > > > > > Yes I agree, and the bindings that are added need to be upstream in
> > > > > > > dt-schema. This applies also to the work that Linaro does.
> > > > > > >
> > > > > > > I will mention this to Sugosh as well as he is adding a public key.
> > > > > >
> > > > > > He is already aware, he is working on a PoC that does exactly what I
> > > > > > described.  Once we verify devices are starting to pass the
> > > > > > SystemReady2.0 certification he will send an RFC
> > > > >
> > > > > What PoC? You mean bindings?
> > > >
> > > > stripping of bindings that are not upstreamed in  the dt-schema
> > >
> > > If that is what you want to do, then the binding needs to go upstream
> > > before we accept his patches.
> >
> > This makes no sense whatsoever.  Sughosh isn't adding anything new.
> > Having the public portion on the DT file is something you insisted
> > upon years ago and even reverted patches from me that had the key as a
> > Kconfig option (which notably suffered from non of these problems, or
> > the increased complexity we are adding now).  What Sughosh is adding
> > is autogenerating that, instead of having to manually stitch the DT.
>
> Yes and it forms part of the machine's DT and needs to have a binding,
> just like the Binman nodes need a binding. Isn't this the whole point?
>
> Either:
> - we upstream the U-Boot bindings, or
> - we allow U-Boot to put whatever it wants in there and accept it

The latter is not an option.  U-Boot is the only certified systemready
bootloader and you are trying to break that.

>
> I much prefer the first option since we can run validation on it, as
> I'm sure you would prefer. But removing nodes before booting just
> because we haven't upstreamed things is just going to lead to no one
> bothering to do it.

If you read up a few mail before you'll figure out no one has to do
that manually.  We can have an array that applies to all internal
bindings and clean them up for all boards.

You've tried to upstream bindings for years and only a handful has
been accepted.  So delaying the certification process because of
internal U-Boot ABI issues isn't really sane for me.

Thanks
/Ilias

>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02 13:55                                                                                                                                                                                                 ` Simon Glass
  2023-08-02 13:59                                                                                                                                                                                                   ` Ilias Apalodimas
@ 2023-08-02 15:38                                                                                                                                                                                                   ` Tom Rini
  1 sibling, 0 replies; 478+ messages in thread
From: Tom Rini @ 2023-08-02 15:38 UTC (permalink / raw)
  To: Simon Glass
  Cc: Ilias Apalodimas, Abdellatif El Khlifi, achin.gupta, nd, u-boot,
	jens.wiklander

[-- Attachment #1: Type: text/plain, Size: 15532 bytes --]

On Wed, Aug 02, 2023 at 07:55:18AM -0600, Simon Glass wrote:
> Hi Ilias,
> 
> On Wed, 2 Aug 2023 at 07:48, Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
> >
> > Hi Simon,
> >
> > On Wed, 2 Aug 2023 at 16:44, Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Ilias,
> > >
> > > On Wed, 2 Aug 2023 at 07:43, Ilias Apalodimas
> > > <ilias.apalodimas@linaro.org> wrote:
> > > >
> > > > On Wed, 2 Aug 2023 at 16:42, Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > Hi Ilias,
> > > > >
> > > > > On Wed, 2 Aug 2023 at 07:38, Ilias Apalodimas
> > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > >
> > > > > > Hi Simon,
> > > > > >
> > > > > > On Wed, 2 Aug 2023 at 16:34, Simon Glass <sjg@chromium.org> wrote:
> > > > > > >
> > > > > > > Hi Ilias,
> > > > > > >
> > > > > > > On Wed, 2 Aug 2023 at 07:27, Ilias Apalodimas
> > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > >
> > > > > > > > Hi Simon,
> > > > > > > >
> > > > > > > >
> > > > > > > > On Wed, 2 Aug 2023 at 16:09, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > >
> > > > > > > > > Hi Ilias,
> > > > > > > > >
> > > > > > > > > On Wed, 2 Aug 2023 at 07:02, Ilias Apalodimas
> > > > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > > > >
> > > > > > > > > > Hi Simon,
> > > > > > > > > >
> > > > > > > > > > On Wed, 2 Aug 2023 at 15:52, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > > > >
> > > > > > > > > > > Hi Ilias,
> > > > > > > > > > >
> > > > > > > > > > > On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
> > > > > > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> > > > > > > > > > > > >
> > > > > > > > > > > > > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > > > > > > > > > > > > Hi guys,
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > > > > > > > > > > > > ...
> > > > > > > > > > > > > > > > > > > > > > Changelog:
> > > > > > > > > > > > > > > > > > > > > > ===============
> > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > v17:
> > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > > > > > > > > > > > > [snip]
> > > > > > > > > > > > > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > > > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > > > > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > > > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > > > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > > > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > > > > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > > > > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > > > > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > > > > > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > > > > > > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > > > > > > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > > > > > > > > > > > > platform.
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > Since FF-A isn't a new
> > > > > > > > > > > > > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > > > > > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > > > > > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > > > > > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > > > > > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > > > > > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > > > > > > > > > > > > easier.
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > > > > > > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > > > > > > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > > > > > > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > > > > > > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > > > > > > > > > > > > here.
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > > > > > > > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > > > > > > > > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > > > > > > > > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > > > > > > > > > > > > addresses show up is as confusing as having Kconfig options for
> > > > > > > > > > > > > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > > > > > > > > > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > > > > > > > > > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > > > > > > > > > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > Tom you prefer that as well?
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > > > > > > > > > > > > fine, especially since default values of 0 are nonsense in this case
> > > > > > > > > > > > > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > > > > > > > > > > > > 0x0 once we do string comparisons).
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > I'd like to give some context why it's important for Corstone-1000 platform
> > > > > > > > > > > > > > that the DT passed to the kernel matches the official kernel DT.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Note that we've set aside the "should this be in DT or not" question.
> > > > > > > > > > > > >
> > > > > > > > > > > > > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > > > > > > > > > > > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > > > > > > > > > > > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > > > > > > > > > > > > to the kernel DT, the DT test will fail.
> > > > > > > > > > > > >
> > > > > > > > > > > > > This is overall good and progress.
> > > > > > > > > > > > >
> > > > > > > > > > > > > > To be approved by the kernel DT maintainers, the node should have a use case
> > > > > > > > > > > > > > in the kernel which is not the case.
> > > > > > > > > > > > >
> > > > > > > > > > > > > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > > > > > > > > > > > > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > > > > > > > > > > > > are in dt-schema and so can be in the upstream kernel but are not used
> > > > > > > > > > > > > in the kernel itself.
> > > > > > > > > > > > >
> > > > > > > > > > > > > > There is a solution for this which is deleting the node we don't want to pass to
> > > > > > > > > > > > > > the kernel using delete-node in the U-Boot DT.
> > > > > > > > > > > > >
> > > > > > > > > > > > > Something like this will likely be needed, in the end, at least for some
> > > > > > > > > > > > > cases.  But the goal is that everything gets in to dt-schema.
> > > > > > > > > > > >
> > > > > > > > > > > > We are already working on U-Boot on that.  The idea is rather simple.
> > > > > > > > > > > > We will have an array with nodes and node entries.  Before we boot up
> > > > > > > > > > > > we'll scan that array, if a node entry exists we will delete that,
> > > > > > > > > > > > otherwise we will just get rid of the entire node.  That should be
> > > > > > > > > > > > pretty easy to maintain and extend.  U-Boot will then be able to use
> > > > > > > > > > > > it;s internal bidings without polluting the DT we handover to the
> > > > > > > > > > > > kernel.
> > > > > > > > > > >
> > > > > > > > > > > This is not pollution - we have moved past that now and Linux has
> > > > > > > > > > > accepted some U-Boot bindings. This is the DT and if there are things
> > > > > > > > > > > in it that are not related to Linux, it can ignore them.
> > > > > > > > > > >
> > > > > > > > > > > We should add whatever bindings we need to make U-Boot work
> > > > > > > > > > > efficiently and correctly.
> > > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > The cases that are already accepted make sense.  Things like the
> > > > > > > > > > public part of the certificates used to authenticate capsule updates
> > > > > > > > > > or the encoding of the recent a/b update nodes are not needed in any
> > > > > > > > > > way in an OS.  Those don't make sense to upstream and those are
> > > > > > > > > > polluting the DT and need stripping
> > > > > > > > >
> > > > > > > > > It doesn't matter that Linux doesn't *need* it. If it is there it will
> > > > > > > > > have to accommodate it. We have loads of Linux stuff in the DT that
> > > > > > > > > means nothing to U-Boot. Many of the bindings chosen by Linux are
> > > > > > > > > wildly inefficient for U-Boot to implement.
> > > > > > > > >
> > > > > > > > > We don't need to strip anything. This is not pollution. It is a
> > > > > > > > > binding agreement between projects.
> > > > > > > > >
> > > > > > > >
> > > > > > > > I am not a maintainer, but I doubt they view it that way.  In any
> > > > > > >
> > > > > > > Who?
> > > > > > >
> > > > > > > > case, the DT produced by u-boot fails to pass the certification on
> > > > > > >
> > > > > > > U-Boot
> > > > > > >
> > > > > > > > every single platform that uses nonupstream nodes, so cleaning that up
> > > > > > > > is needed.  If people care enough and upstream those bindings we can
> > > > > > > > preserve them
> > > > > > >
> > > > > > > Yes I agree, and the bindings that are added need to be upstream in
> > > > > > > dt-schema. This applies also to the work that Linaro does.
> > > > > > >
> > > > > > > I will mention this to Sugosh as well as he is adding a public key.
> > > > > >
> > > > > > He is already aware, he is working on a PoC that does exactly what I
> > > > > > described.  Once we verify devices are starting to pass the
> > > > > > SystemReady2.0 certification he will send an RFC
> > > > >
> > > > > What PoC? You mean bindings?
> > > >
> > > > stripping of bindings that are not upstreamed in  the dt-schema
> > >
> > > If that is what you want to do, then the binding needs to go upstream
> > > before we accept his patches.
> >
> > This makes no sense whatsoever.  Sughosh isn't adding anything new.
> > Having the public portion on the DT file is something you insisted
> > upon years ago and even reverted patches from me that had the key as a
> > Kconfig option (which notably suffered from non of these problems, or
> > the increased complexity we are adding now).  What Sughosh is adding
> > is autogenerating that, instead of having to manually stitch the DT.
> 
> Yes and it forms part of the machine's DT and needs to have a binding,
> just like the Binman nodes need a binding. Isn't this the whole point?
> 
> Either:
> - we upstream the U-Boot bindings, or
> - we allow U-Boot to put whatever it wants in there and accept it
> 
> I much prefer the first option since we can run validation on it, as
> I'm sure you would prefer. But removing nodes before booting just
> because we haven't upstreamed things is just going to lead to no one
> bothering to do it.

I think we're talking past each other now.  All of the following are
true:
- It has historically been hard to get bindings accepted that are not
  used in the linux kernel.
- It is not only possible but reasonable today to get bindings accepted
  that are not used in the linux kernel.
- There are many bindings outstanding today that need to be adjusted,
  upstreamed and accepted to dt-schema.
- For SystemReady certification, U-Boot _is_ an important part of the
  ecosystem.
- U-Boot as a project sees this as important (and I personally see this
  as important).
- SystemReady is going to be more strict about what can / can't be in
  the device tree.  This is good because it will prioritize accepted
  bindings rather than "garbage" bindings.
- Today, one can just chain up "fdt" commands to make this happen.
- In the future, we'll have a cleaner way to do this.  This is good
  because it means we won't hide these behind environment strings and so
  forth to "sneak" in, but instead be pragmatic about it. Heck, we
  should make one of the conditions for being listed there be a link to
  discussion on upstreaming OR why it's inappropriate. This will make
  sure it doesn't stifle the upstreaming of bindings.
- Using non-upstreamed bindings in the device tree passed to the kernel
  is at least as big a deal, if not bigger a deal, for the vendor kernel
  tree than it is for U-Boot.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication
  2023-08-02 13:59                                                                                                                                                                                                   ` Ilias Apalodimas
@ 2023-08-02 16:10                                                                                                                                                                                                     ` Simon Glass
  0 siblings, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-08-02 16:10 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Tom Rini, Abdellatif El Khlifi, achin.gupta, nd, u-boot, jens.wiklander

Hi Ilias,

On Wed, 2 Aug 2023 at 08:00, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Simon,
>
> On Wed, 2 Aug 2023 at 16:55, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Ilias,
> >
> > On Wed, 2 Aug 2023 at 07:48, Ilias Apalodimas
> > <ilias.apalodimas@linaro.org> wrote:
> > >
> > > Hi Simon,
> > >
> > > On Wed, 2 Aug 2023 at 16:44, Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Ilias,
> > > >
> > > > On Wed, 2 Aug 2023 at 07:43, Ilias Apalodimas
> > > > <ilias.apalodimas@linaro.org> wrote:
> > > > >
> > > > > On Wed, 2 Aug 2023 at 16:42, Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > Hi Ilias,
> > > > > >
> > > > > > On Wed, 2 Aug 2023 at 07:38, Ilias Apalodimas
> > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > >
> > > > > > > Hi Simon,
> > > > > > >
> > > > > > > On Wed, 2 Aug 2023 at 16:34, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > >
> > > > > > > > Hi Ilias,
> > > > > > > >
> > > > > > > > On Wed, 2 Aug 2023 at 07:27, Ilias Apalodimas
> > > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > > >
> > > > > > > > > Hi Simon,
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > On Wed, 2 Aug 2023 at 16:09, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > > >
> > > > > > > > > > Hi Ilias,
> > > > > > > > > >
> > > > > > > > > > On Wed, 2 Aug 2023 at 07:02, Ilias Apalodimas
> > > > > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > > > > >
> > > > > > > > > > > Hi Simon,
> > > > > > > > > > >
> > > > > > > > > > > On Wed, 2 Aug 2023 at 15:52, Simon Glass <sjg@chromium.org> wrote:
> > > > > > > > > > > >
> > > > > > > > > > > > Hi Ilias,
> > > > > > > > > > > >
> > > > > > > > > > > > On Wed, 2 Aug 2023 at 00:52, Ilias Apalodimas
> > > > > > > > > > > > <ilias.apalodimas@linaro.org> wrote:
> > > > > > > > > > > > >
> > > > > > > > > > > > > On Tue, 1 Aug 2023 at 19:19, Tom Rini <trini@konsulko.com> wrote:
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > On Tue, Aug 01, 2023 at 05:10:08PM +0100, Abdellatif El Khlifi wrote:
> > > > > > > > > > > > > > > Hi guys,
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > On Tue, Aug 01, 2023 at 11:00:57AM -0400, Tom Rini wrote:
> > > > > > > > > > > > > > > > > > > > > > > ...
> > > > > > > > > > > > > > > > > > > > > > > Changelog:
> > > > > > > > > > > > > > > > > > > > > > > ===============
> > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > > v17:
> > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > > * show a debug message rather than an error when FF-A is not detected
> > > > > > > > > > > > > > > > > > > > > > [snip]
> > > > > > > > > > > > > > > > > > > > > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > > > > index c5835e6ef6..8fbadb9201 100644
> > > > > > > > > > > > > > > > > > > > > > > --- a/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > > > > +++ b/lib/efi_loader/Kconfig
> > > > > > > > > > > > > > > > > > > > > > > @@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
> > > > > > > > > > > > > > > > > > > > > > >         stored as file /ubootefi.var on the EFI system partition.
> > > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > >  config EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > > > > > > > -     bool "UEFI variables storage service via OP-TEE"
> > > > > > > > > > > > > > > > > > > > > > > -     depends on OPTEE
> > > > > > > > > > > > > > > > > > > > > > > +     bool "UEFI variables storage service via the trusted world"
> > > > > > > > > > > > > > > > > > > > > > > +     depends on OPTEE && ARM_FFA_TRANSPORT
> > > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > > You didn't get my changes in here however. If you can do EFI_MM_COMM_TEE
> > > > > > > > > > > > > > > > > > > > > > without ARM_FFA_TRANSPORT (as lx2160ardb_tfa_stmm_defconfig does) then
> > > > > > > > > > > > > > > > > > > > > > you don't make this option depend on .  If FF-A is only
> > > > > > > > > > > > > > > > > > > > > > for use here, you make FF-A depend on this, and the FF-A specific
> > > > > > > > > > > > > > > > > > > > > > variable depend on ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > Abdellatif hinted at what's going on here.  When I added this Kconfig
> > > > > > > > > > > > > > > > > > > > > option to lx2160 FF-A wasn't implemented yet.
> > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > The defconfig has existed since May 2020, which is when you added
> > > > > > > > > > > > > > > > > > > > EFI_MM_COMM_TEE itself too.  So I think it's that no one did the check I
> > > > > > > > > > > > > > > > > > > > did until now and saw this series was disabling what was on the other
> > > > > > > > > > > > > > > > > > > > platform.
> > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > > Since FF-A isn't a new
> > > > > > > > > > > > > > > > > > > > > communication mechanism but builds upon the existing SMCs to build an
> > > > > > > > > > > > > > > > > > > > > easier API, I asked Abdellatif to hide this complexity.
> > > > > > > > > > > > > > > > > > > > > We had two options, either make Kconfig options for either FF-A or the
> > > > > > > > > > > > > > > > > > > > > traditional SMCs and remove the dependencies,  or piggyback on FF-As
> > > > > > > > > > > > > > > > > > > > > discovery mechanism and make the choice at runtime.  The latter has a
> > > > > > > > > > > > > > > > > > > > > small impact on code size, but imho makes developers' life a lot
> > > > > > > > > > > > > > > > > > > > > easier.
> > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > > I'm not sure how much you can do a run-time option here since you're
> > > > > > > > > > > > > > > > > > > > setting a bunch of default values for FF-A to 0 in Kconfig.  If we're
> > > > > > > > > > > > > > > > > > > > supposed to be able to get them at run time, we shouldn't need a Kconfig
> > > > > > > > > > > > > > > > > > > > option at all.  I'm also not sure how valid a use case it is where we
> > > > > > > > > > > > > > > > > > > > won't know at build time what the rest of the firmware stack supports
> > > > > > > > > > > > > > > > > > > > here.
> > > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > > That's a fair point.  FF-A in theory has APIs to discover memory.
> > > > > > > > > > > > > > > > > > > Abdellatif, why do we need the Kconfigs for shared memory on FF-A?
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > The statically carved out MM shared buffer address, size and offset cannot be discovered by FF-A ABIs.
> > > > > > > > > > > > > > > > > > The MM communication driver in U-Boot could allocate the buffer and share it with the MM SP but
> > > > > > > > > > > > > > > > > > we do not implement that support currently in either U-Boot or UEFI.
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > Ok, that's a bit unfortunate, but Tom is right.  Having the FF-A
> > > > > > > > > > > > > > > > > addresses show up is as confusing as having Kconfig options for
> > > > > > > > > > > > > > > > > discrete options.  The whole point of my suggestion was to make users'
> > > > > > > > > > > > > > > > > lives easier.  Apologies for the confusion but can you bring back the
> > > > > > > > > > > > > > > > > ifdefs?  Looking at the patch this should be minimal just use
> > > > > > > > > > > > > > > > > ifdef ARM_FFA_TRANSPORT and ifndef ARM_FFA_TRANSPORT.
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > Tom you prefer that as well?
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > Pending an answer to Jens' feedback, yes, going back to #ifdef's is
> > > > > > > > > > > > > > > > fine, especially since default values of 0 are nonsense in this case
> > > > > > > > > > > > > > > > (and as Heinrich's patch re SYS_MALLOC_LEN shows, dangerous since 0 !=
> > > > > > > > > > > > > > > > 0x0 once we do string comparisons).
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > I'd like to give some context why it's important for Corstone-1000 platform
> > > > > > > > > > > > > > > that the DT passed to the kernel matches the official kernel DT.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > Note that we've set aside the "should this be in DT or not" question.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > > There is a SystemReady IR 2.0 test checking the DT. It compares the DT
> > > > > > > > > > > > > > > passed by U-Boot with a reference DT (the kernel DT) . The test fails if there
> > > > > > > > > > > > > > > is a mismatch. So, if we add a DT node in U-Boot and the node is not upstreamed
> > > > > > > > > > > > > > > to the kernel DT, the DT test will fail.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > This is overall good and progress.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > > To be approved by the kernel DT maintainers, the node should have a use case
> > > > > > > > > > > > > > > in the kernel which is not the case.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > This is, I believe / hope wrong.  It needs to be in the dt-schema
> > > > > > > > > > > > > > repository, not strictly "the kernel".  For example, bootph-all (etc)
> > > > > > > > > > > > > > are in dt-schema and so can be in the upstream kernel but are not used
> > > > > > > > > > > > > > in the kernel itself.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > > There is a solution for this which is deleting the node we don't want to pass to
> > > > > > > > > > > > > > > the kernel using delete-node in the U-Boot DT.
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > Something like this will likely be needed, in the end, at least for some
> > > > > > > > > > > > > > cases.  But the goal is that everything gets in to dt-schema.
> > > > > > > > > > > > >
> > > > > > > > > > > > > We are already working on U-Boot on that.  The idea is rather simple.
> > > > > > > > > > > > > We will have an array with nodes and node entries.  Before we boot up
> > > > > > > > > > > > > we'll scan that array, if a node entry exists we will delete that,
> > > > > > > > > > > > > otherwise we will just get rid of the entire node.  That should be
> > > > > > > > > > > > > pretty easy to maintain and extend.  U-Boot will then be able to use
> > > > > > > > > > > > > it;s internal bidings without polluting the DT we handover to the
> > > > > > > > > > > > > kernel.
> > > > > > > > > > > >
> > > > > > > > > > > > This is not pollution - we have moved past that now and Linux has
> > > > > > > > > > > > accepted some U-Boot bindings. This is the DT and if there are things
> > > > > > > > > > > > in it that are not related to Linux, it can ignore them.
> > > > > > > > > > > >
> > > > > > > > > > > > We should add whatever bindings we need to make U-Boot work
> > > > > > > > > > > > efficiently and correctly.
> > > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > The cases that are already accepted make sense.  Things like the
> > > > > > > > > > > public part of the certificates used to authenticate capsule updates
> > > > > > > > > > > or the encoding of the recent a/b update nodes are not needed in any
> > > > > > > > > > > way in an OS.  Those don't make sense to upstream and those are
> > > > > > > > > > > polluting the DT and need stripping
> > > > > > > > > >
> > > > > > > > > > It doesn't matter that Linux doesn't *need* it. If it is there it will
> > > > > > > > > > have to accommodate it. We have loads of Linux stuff in the DT that
> > > > > > > > > > means nothing to U-Boot. Many of the bindings chosen by Linux are
> > > > > > > > > > wildly inefficient for U-Boot to implement.
> > > > > > > > > >
> > > > > > > > > > We don't need to strip anything. This is not pollution. It is a
> > > > > > > > > > binding agreement between projects.
> > > > > > > > > >
> > > > > > > > >
> > > > > > > > > I am not a maintainer, but I doubt they view it that way.  In any
> > > > > > > >
> > > > > > > > Who?
> > > > > > > >
> > > > > > > > > case, the DT produced by u-boot fails to pass the certification on
> > > > > > > >
> > > > > > > > U-Boot
> > > > > > > >
> > > > > > > > > every single platform that uses nonupstream nodes, so cleaning that up
> > > > > > > > > is needed.  If people care enough and upstream those bindings we can
> > > > > > > > > preserve them
> > > > > > > >
> > > > > > > > Yes I agree, and the bindings that are added need to be upstream in
> > > > > > > > dt-schema. This applies also to the work that Linaro does.
> > > > > > > >
> > > > > > > > I will mention this to Sugosh as well as he is adding a public key.
> > > > > > >
> > > > > > > He is already aware, he is working on a PoC that does exactly what I
> > > > > > > described.  Once we verify devices are starting to pass the
> > > > > > > SystemReady2.0 certification he will send an RFC
> > > > > >
> > > > > > What PoC? You mean bindings?
> > > > >
> > > > > stripping of bindings that are not upstreamed in  the dt-schema
> > > >
> > > > If that is what you want to do, then the binding needs to go upstream
> > > > before we accept his patches.
> > >
> > > This makes no sense whatsoever.  Sughosh isn't adding anything new.
> > > Having the public portion on the DT file is something you insisted
> > > upon years ago and even reverted patches from me that had the key as a
> > > Kconfig option (which notably suffered from non of these problems, or
> > > the increased complexity we are adding now).  What Sughosh is adding
> > > is autogenerating that, instead of having to manually stitch the DT.
> >
> > Yes and it forms part of the machine's DT and needs to have a binding,
> > just like the Binman nodes need a binding. Isn't this the whole point?
> >
> > Either:
> > - we upstream the U-Boot bindings, or
> > - we allow U-Boot to put whatever it wants in there and accept it
>
> The latter is not an option.  U-Boot is the only certified systemready
> bootloader and you are trying to break that.

I am missing something here, to say the least.

>
> >
> > I much prefer the first option since we can run validation on it, as
> > I'm sure you would prefer. But removing nodes before booting just
> > because we haven't upstreamed things is just going to lead to no one
> > bothering to do it.
>
> If you read up a few mail before you'll figure out no one has to do
> that manually.  We can have an array that applies to all internal
> bindings and clean them up for all boards.
>
> You've tried to upstream bindings for years and only a handful has
> been accepted.

Can you find something here? I remember perhaps sending one (uart
clock-frequency?), but it was mostly the discussions with a kernel
maintainer that made me see it was a waste of time. Of course my
memory is not that great. It is certainly true that I gave up a long
time ago and only restarted due to a change of guard.

> So delaying the certification process because of
> internal U-Boot ABI issues isn't really sane for me.

I am not suggesting that...we just need to upstream our bindings. That
is all. If there is no path to upstream, then we either have a bad
binding or we have a process / people problem. Either way, we should
fix it and carry on.

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v18 0/9] introduce Arm FF-A support
  2023-08-02  6:51                                                                                                                                                                           ` Ilias Apalodimas
  2023-08-02 12:52                                                                                                                                                                             ` Simon Glass
@ 2023-08-03 16:03                                                                                                                                                                             ` Abdellatif El Khlifi
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 1/9] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                                                                                                                                                                 ` (8 more replies)
  1 sibling, 9 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-03 16:03 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: abdellatif.elkhlifi, achin.gupta, jens.wiklander, nd, sjg, trini,
	u-boot, Rob Herring, Drew Reed, Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].

FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
communicate with each other. A partition could be a VM in the Normal or Secure world, an
application in S-EL0, or a Trusted OS in S-EL1.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

   => dm tree

    Class     Index  Probed  Driver                Name
   -----------------------------------------------------------
   ...
    firmware      0  [ + ]   psci                      |-- psci
    ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
   ...

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

This implementation of the specification provides support for Aarch64.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

    - Discover the presence of secure partitions (SPs) of interest
    - Access an SP's service through communication protocols
      (e.g: EFI MM communication protocol)

The FF-A support provides the following features:

    - Being generic by design and can be used by any Arm 64-bit platform
    - FF-A support can be compiled and used without EFI
    - Support for SMCCCv1.2 x0-x17 registers
    - Support for SMC32 calling convention
    - Support for 32-bit and 64-bit FF-A direct messaging
    - Support for FF-A MM communication (compatible with EFI boot time)
    - Enabling FF-A and MM communication in Corstone1000 platform as a use case
    - 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.
    - Sandbox FF-A test cases.
    - A new command called armffa is provided as an example of how to access the
      FF-A bus

For more details about the FF-A support please refer to [B] and refer to [C] for
how to use the armffa command.

Please find at [D] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of changes:
===========================

v18:

Ilias, Tom:

* drop the use of configs for the shared MM buffer, put back #ifdefs instead
* add test information to the MM comms commit message

v17: [17]

Ilias:

* show a debug message rather than an error when FF-A is not detected

Tom:

* use savedefconfig to generate corstone1000_defconfig with FF-A MM comms enabled

v16: [16]

Tom:

* lib/efi_loader/Kconfig:
   rather than automatically selecting OPTEE and ARM_FFA_TRANSPORT configs by
   EFI_MM_COMM_TEE, set them as dependencies (Otherwise FF-A will be automatically
   enabled for boards that don't need it).

* configs/corstone1000_defconfig:
   enable MM communication by setting the configs: ARM_FFA_TRANSPORT, OPTEE, TEE

v15: [15]

Simon:

* drop commit "log: select physical address formatting in a generic way",
   this will be sent as a follow-up commit independently from this patchset
* armffa.c : integrate PHYS_ADDR_LN
* replace FFA_SHARED_MM_BUFFER_* defines with configs

v14: [14]

Simon:

    * add to log.h a generic physical address formatting

Ilias:

    * armffa command: in do_ffa_ping() reject the SP ID if it's 0
    * MM comms: drop truncating var_payload->size when using FF-A
    * MM comms: map the MM SP return codes to errnos
    * address nits

v13: [13]

Ilias:
    * remove FF-A and Optee ifdefs in efi_variable_tee.c
    * doc minor change: specify in the readme that the user
       should call ffa_rxtx_unmap() driver operation to unmap
       the RX/TX buffers on demand.

v12: [12]

* remove the global variable (dscvry_info), use uc_priv instead
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* remove reparenting by making the sandbox emulator parent of the FF-A device in the DT
* improve argument checks for the armffa command
* address nits

v11: [11]

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* use U_BOOT_CMD_WITH_SUBCMDS for armffa command
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device
* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* use ut_asserteq_mem() in uuid_str_to_le_bin test case
* address nits

v10: [10]

* provide the FF-A driver operations through the Uclass (arm-ffa-uclass.c)
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c renamed from core.c)
* split the FF-A sandbox support into an emulator (ffa-emul-uclass.c) and a driver (sandbox_ffa.c)
* use the FF-A driver Uclass operations by clients (armffa command, tests, MM comms)
* use uclass_first_device to search and probe the FF-A device (whether it is on Arm or on sandbox)
* address nits

v9: [9]

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
* align FF-A sandbox driver with FF-A discovery through DM
* use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
* add documentation for the armffa command: doc/usage/cmd/armffa.rst
* introduce testcase for uuid_str_to_le_bin

v8: [8]

* pass the FF-A bus device to the bus operations
* isolate the compilation choices between FF-A and OP-TEE
* drop OP-TEE configs from Corstone-1000 defconfig
* make ffa_get_partitions_info() second argument to be an SP count in both
  modes

v7: [7]

* add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v6: [6]

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

List of previous patches:

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
[7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
[8]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
[9]: https://lore.kernel.org/all/20230310141016.137986-1-abdellatif.elkhlifi@arm.com/
[10]: https://lore.kernel.org/all/20230328161157.219375-1-abdellatif.elkhlifi@arm.com/
[11]: https://lore.kernel.org/all/20230412094245.44674-1-abdellatif.elkhlifi@arm.com/
[12]: https://lore.kernel.org/all/20230512121044.111574-1-abdellatif.elkhlifi@arm.com/
[13]: https://lore.kernel.org/all/20230616152817.319869-1-abdellatif.elkhlifi@arm.com/
[14]: https://lore.kernel.org/all/20230707144410.228472-1-abdellatif.elkhlifi@arm.com/
[15]: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/
[16]: https://lore.kernel.org/all/20230726094503.100497-1-abdellatif.elkhlifi@arm.com/
[17]: https://lore.kernel.org/all/20230727160712.81477-1-abdellatif.elkhlifi@arm.com/

More details:

[A]: https://developer.arm.com/documentation/den0077/latest/
[B]: doc/arch/arm64.ffa.rst
[C]: doc/usage/cmd/armffa.rst
[D]: example of boot logs when enabling FF-A

```
   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64

   DRAM:  2 GiB
   Arm FF-A framework discovery
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   ...
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   EFI: MM partition ID 0x8003
   ...
   EFI stub: Booting Linux Kernel...
   ...
   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
   Machine model: ARM Corstone1000 FPGA MPS3 board
```

Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (9):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce uuid_str_to_le_bin function
  lib: uuid: introduce testcase for uuid_str_to_le_bin
  arm_ffa: introduce Arm FF-A support
  arm_ffa: introduce sandbox FF-A support
  arm_ffa: introduce sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   18 +
 arch/arm/cpu/armv8/smccc-call.S               |   57 +-
 arch/arm/lib/asm-offsets.c                    |   16 +
 arch/sandbox/dts/sandbox.dtsi                 |    9 +
 arch/sandbox/dts/test.dts                     |    8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |   72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        |  121 ++
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    1 +
 cmd/armffa.c                                  |  202 ++++
 configs/corstone1000_defconfig                |   10 +-
 configs/sandbox64_defconfig                   |    1 +
 configs/sandbox_defconfig                     |    1 +
 doc/arch/arm64.ffa.rst                        |  261 ++++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox/sandbox.rst                  |    1 +
 doc/usage/cmd/armffa.rst                      |   94 ++
 doc/usage/index.rst                           |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   42 +
 drivers/firmware/arm-ffa/Makefile             |   16 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 drivers/firmware/arm-ffa/ffa-emul-uclass.c    |  720 +++++++++++
 drivers/firmware/arm-ffa/sandbox_ffa.c        |  110 ++
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/dm/uclass-id.h                        |    7 +
 include/linux/arm-smccc.h                     |   45 +
 include/mm_communication.h                    |   17 +
 include/uuid.h                                |   15 +
 lib/efi_loader/Kconfig                        |   42 +-
 lib/efi_loader/efi_variable_tee.c             |  282 ++++-
 lib/uuid.c                                    |   48 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   33 +
 test/dm/Makefile                              |    3 +-
 test/dm/ffa.c                                 |  261 ++++
 test/lib/Makefile                             |    1 +
 test/lib/uuid.c                               |   41 +
 41 files changed, 4186 insertions(+), 13 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 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 doc/usage/cmd/armffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/lib/uuid.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v18 1/9] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-08-03 16:03                                                                                                                                                                             ` [PATCH v18 0/9] introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-08-03 16:03                                                                                                                                                                               ` Abdellatif El Khlifi
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 2/9] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
                                                                                                                                                                                                 ` (7 subsequent siblings)
  8 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-03 16:03 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: abdellatif.elkhlifi, achin.gupta, jens.wiklander, nd, sjg, trini, u-boot

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>

---

Changelog:
===============

v9:

* update the copyright string

v7:

* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

 arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
 arch/arm/lib/asm-offsets.c      | 16 +++++++++
 include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..93f66d3366 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,7 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
- */
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+*/
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
 #include <generated/asm-offsets.h>
@@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 6de0ce9152..181a8ac4c2 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,11 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * 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>
@@ -90,6 +95,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#ifdef CONFIG_ARM64
+	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..f44e9e8f93 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +74,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v18 2/9] lib: uuid: introduce uuid_str_to_le_bin function
  2023-08-03 16:03                                                                                                                                                                             ` [PATCH v18 0/9] introduce Arm FF-A support Abdellatif El Khlifi
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 1/9] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-08-03 16:03                                                                                                                                                                               ` Abdellatif El Khlifi
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 3/9] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
                                                                                                                                                                                                 ` (6 subsequent siblings)
  8 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-03 16:03 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: abdellatif.elkhlifi, achin.gupta, jens.wiklander, nd, sjg, trini, u-boot

convert UUID string to little endian binary data

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v9:

* add a full function prototype description in uuid.h

v8:

* use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

 include/uuid.h | 15 +++++++++++++++
 lib/uuid.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..89b93e642b 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,10 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +48,15 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ * Return:
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 96e1af3c8b..45f325d964 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * 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>
@@ -354,6 +358,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16;
+	u32 tmp32;
+	u64 tmp64;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+	memcpy(uuid_bin, &tmp32, 4);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16));
+	memcpy(uuid_bin + 10, &tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v18 3/9] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-08-03 16:03                                                                                                                                                                             ` [PATCH v18 0/9] introduce Arm FF-A support Abdellatif El Khlifi
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 1/9] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 2/9] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2023-08-03 16:03                                                                                                                                                                               ` Abdellatif El Khlifi
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 4/9] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                 ` (5 subsequent siblings)
  8 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-03 16:03 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: abdellatif.elkhlifi, achin.gupta, jens.wiklander, nd, sjg, trini, u-boot

provide a test case

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>

---

Changelog:
===============

v16:

* MAINTAINERS: place the UUID part in an alphabetical order

v11:

* use ut_asserteq_mem()

 MAINTAINERS       |  5 +++++
 test/lib/Makefile |  1 +
 test/lib/uuid.c   | 41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)
 create mode 100644 test/lib/uuid.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d724b64673..4324965d26 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1555,6 +1555,11 @@ T:	git https://source.denx.de/u-boot/custodians/u-boot-usb.git topic-xhci
 F:	drivers/usb/host/xhci*
 F:	include/usb/xhci.h
 
+UUID testing
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	test/lib/uuid.c
+
 VIDEO
 M:	Anatolij Gustschin <agust@denx.de>
 S:	Maintained
diff --git a/test/lib/Makefile b/test/lib/Makefile
index e0bd9e04e8..e75a263e6a 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_AES) += test_aes.o
 obj-$(CONFIG_GETOPT) += getopt.o
 obj-$(CONFIG_CRC8) += test_crc8.o
 obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o
+obj-$(CONFIG_LIB_UUID) += uuid.o
 else
 obj-$(CONFIG_SANDBOX) += kconfig_spl.o
 endif
diff --git a/test/lib/uuid.c b/test/lib/uuid.c
new file mode 100644
index 0000000000..e24331a136
--- /dev/null
+++ b/test/lib/uuid.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <uuid.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* test UUID */
+#define TEST_SVC_UUID	"ed32d533-4209-99e6-2d72-cdd998a79cc0"
+
+#define UUID_SIZE 16
+
+/* The UUID binary data (little-endian format) */
+static const u8 ref_uuid_bin[UUID_SIZE] = {
+	0x33, 0xd5, 0x32, 0xed,
+	0x09, 0x42, 0xe6, 0x99,
+	0x72, 0x2d, 0xc0, 0x9c,
+	0xa7, 0x98, 0xd9, 0xcd
+};
+
+static int lib_test_uuid_to_le(struct unit_test_state *uts)
+{
+	const char *uuid_str = TEST_SVC_UUID;
+	u8 ret_uuid_bin[UUID_SIZE] = {0};
+
+	ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin));
+	ut_asserteq_mem(ref_uuid_bin, ret_uuid_bin, UUID_SIZE);
+
+	return 0;
+}
+
+LIB_TEST(lib_test_uuid_to_le, 0);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v18 4/9] arm_ffa: introduce Arm FF-A support
  2023-08-03 16:03                                                                                                                                                                             ` [PATCH v18 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                 ` (2 preceding siblings ...)
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 3/9] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-08-03 16:03                                                                                                                                                                               ` Abdellatif El Khlifi
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 5/9] arm_ffa: introduce sandbox " Abdellatif El Khlifi
                                                                                                                                                                                                 ` (4 subsequent siblings)
  8 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-03 16:03 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: abdellatif.elkhlifi, achin.gupta, jens.wiklander, nd, sjg, trini,
	u-boot, Heinrich Schuchardt

Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- ffa_partition_info_get
- ffa_sync_send_receive
- ffa_rxtx_unmap

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 please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v13:

* doc minor change: specify in the readme that the user
   should call ffa_rxtx_unmap() driver operation to unmap
   the RX/TX buffers on demand.

v12:

* remove dscvry_info
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* address nits

v11:

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* pass dev as an argument of arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* add emul field in struct ffa_discovery_info
* address nits

v10:

* provide the driver operations through the Uclass
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c)
* rename core.c to arm-ffa.c
* address nits

v9:

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding

v8:

* make ffa_get_partitions_info() second argument to be an SP count in both
  modes
* update ffa_bus_prvdata_get() to return a pointer rather than a pointer
  address
* remove packing from ffa_partition_info and ffa_send_direct_data structures
* pass the FF-A bus device to the bus operations

v7:

* add support for 32-bit direct messaging
* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* improve the declaration of error handling mapping
* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the U-Boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the U-Boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

 MAINTAINERS                                   |    8 +
 doc/arch/arm64.ffa.rst                        |  236 ++++
 doc/arch/index.rst                            |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   36 +
 drivers/firmware/arm-ffa/Makefile             |    8 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |   14 +
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/dm/uclass-id.h                        |    6 +
 13 files changed, 1939 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 4324965d26..4fd5768de0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,6 +266,14 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+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>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..df18948774
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,236 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Support
+================
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
+communicate with each other. A partition could be a VM in the Normal or Secure world, an
+application in S-EL0, or a Trusted OS in S-EL1.
+
+The U-Boot FF-A support (the bus) implements the interfaces to communicate
+with partitions in the Secure world aka Secure partitions (SPs).
+
+The FF-A support specifically focuses on communicating with SPs that
+isolate portions of EFI runtime services that must run in a protected
+environment which is inaccessible by the Host OS or Hypervisor.
+Examples of such services are set/get variables.
+
+The FF-A support uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+At this stage of development only EFI boot-time services are supported.
+Runtime support will be added in future developments.
+
+The U-Boot FF-A support provides the following parts:
+
+- A Uclass driver providing generic FF-A methods.
+- An Arm FF-A device driver providing Arm-specific methods and reusing the Uclass methods.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the U-Boot FF-A support relies on
+`FF-A v1.0 specification`_ and uses SMC32 calling convention which
+means using the first 32-bit data of the Xn registers.
+
+At this stage we only need the FF-A v1.0 features.
+
+The FF-A support has been tested with OP-TEE which supports SMC32 calling
+convention.
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A support uses 64-bit registers as per `SMC Calling Convention v1.2 specification`_.
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+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.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers.
+Then, an SMC instruction is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-Boot Arm FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs.
+
+FF-A bus discovery on Arm 64-bit platforms
+---------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
+an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
+This discovery mechanism is performed by the PSCI driver.
+
+The PSCI driver comes with a PSCI device tree node which is the root node for all
+architecture features including FF-A bus.
+
+::
+
+   => dm tree
+
+    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.
+
+In case of FF-A, the callback is arm_ffa_is_supported() which tries to discover the
+FF-A framework by querying the FF-A framework version from secure world using
+FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
+mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver
+with the device using device_bind_driver().
+
+At this stage the FF-A bus is registered with the DM and can be interacted with using
+the DM APIs.
+
+Clients are able to probe then use the FF-A bus by calling uclass_first_device().
+
+When calling uclass_first_device(), the FF-A driver is probed and ends up calling
+ffa_do_probe() provided by the Uclass which does the following:
+
+    - saving the FF-A framework version in uc_priv
+    - querying from secure world the u-boot endpoint ID
+    - querying from secure world the supported features of FFA_RXTX_MAP
+    - mapping the RX/TX buffers
+    - querying from secure world all the partitions information
+
+When one of the above actions fails, probing fails and the driver stays not active
+and can be probed again if needed.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must query the SPs they are looking for
+during EFI boot-time mode using the service UUID.
+
+The RX/TX buffers are only available at EFI boot-time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped before EFI runtime mode starts.
+The driver provides a bus operation for that called ffa_rxtx_unmap().
+
+The user should call ffa_rxtx_unmap() to unmap the RX/TX buffers when required
+(e.g: at efi_exit_boot_services()).
+
+The Linux kernel allocates its own RX/TX buffers. To be able to register these kernel buffers
+with secure world, the U-Boot's RX/TX buffers should be unmapped before EFI runtime starts.
+
+When invoking FF-A direct messaging, clients should specify which ABI protocol
+they want to use (32-bit vs 64-bit). Selecting the protocol means using
+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
+The calling convention between U-Boot and the secure world stays the same: SMC32.
+
+Requirements for user drivers
+-------------------------------------
+
+Users who want to implement their custom FF-A device driver while reusing the FF-A Uclass can do so
+by implementing their own invoke_ffa_fn() in the user driver.
+
+The bus driver layer
+------------------------------
+
+FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c
+
+The following features are provided:
+
+- Support for the 32-bit version of the following ABIs:
+
+    - FFA_VERSION
+    - FFA_ID_GET
+    - FFA_FEATURES
+    - FFA_PARTITION_INFO_GET
+    - FFA_RXTX_UNMAP
+    - FFA_RX_RELEASE
+    - FFA_RUN
+    - FFA_ERROR
+    - FFA_SUCCESS
+    - FFA_INTERRUPT
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Support for the 64-bit version of the following ABIs:
+
+    - FFA_RXTX_MAP
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, FF-A support takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- FF-A support provides driver operations to be used by upper layers:
+
+    - ffa_partition_info_get
+    - ffa_sync_send_receive
+    - ffa_rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+Example of boot logs with FF-A enabled
+--------------------------------------
+
+For example, when using FF-A with Corstone-1000 the logs are as follows:
+
+::
+
+   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64
+
+   DRAM:  2 GiB
+   Arm FF-A framework discovery
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   ...
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   EFI: MM partition ID 0x8003
+   ...
+   EFI stub: Booting Linux Kernel...
+   ...
+   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
+   Machine model: ARM Corstone1000 FPGA MPS3 board
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+
+.. _`FF-A v1.0 specification`: https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e
+.. _`SMC Calling Convention v1.2 specification`: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index b8da4b8c8e..2f916f4026 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Makefile b/drivers/Makefile
index 78dcf62f76..5044f45253 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -115,6 +115,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index eae1c8ddc9..8789b1ea14 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
 	  the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
 	  services if any and reported as supported by the SMCCC firmware.
 
+source "drivers/firmware/arm-ffa/Kconfig"
 source "drivers/firmware/scmi/Kconfig"
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..9200c8028b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select ARM_SMCCC_FEATURES
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
+	  FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
+	  by the PSCI driver.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  The FF-A support on U-Boot  takes care of all the interactions between Normal
+	  world and Secure World.
+
+	  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
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..11b1766285
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,8 @@
+# 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>
+
+obj-y += arm-ffa-uclass.o arm-ffa.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..ffa9d81fa7
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,1065 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	[NOT_SUPPORTED] = -EOPNOTSUPP,
+	[INVALID_PARAMETERS] = -EINVAL,
+	[NO_MEMORY] = -ENOMEM,
+	[BUSY] = -EBUSY,
+	[INTERRUPTED] = -EINTR,
+	[DENIED] = -EACCES,
+	[RETRY] = -EAGAIN,
+	[ABORTED] = -ECANCELED,
+};
+
+static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			[NO_MEMORY] =
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			[BUSY] =
+			"BUSY: RX buffer of the caller is not free",
+			[DENIED] =
+			"DENIED: Callee is not in a state to handle this request",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			[DENIED] =
+			"DENIED: Caller did not have ownership of the RX buffer",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			[NO_MEMORY] =
+			"NO_MEMORY: Not enough memory",
+			[DENIED] =
+			"DENIED: Buffer pair already registered",
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno() - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+static int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* Map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+static int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* Map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	log_err("%s\n", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/* FF-A ABIs implementation (U-Boot side) */
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void __weak invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+}
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	log_info("FF-A driver %d.%d\nFF-A framework %d.%d\n",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) {
+		log_info("FF-A versions are compatible\n");
+
+		if (dev) {
+			uc_priv = dev_get_uclass_priv(dev);
+			if (uc_priv)
+				uc_priv->fwk_version = res.a0;
+		}
+
+		return 0;
+	}
+
+	log_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id() - FFA_ID_GET handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		uc_priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		log_debug("FF-A endpoint ID is %u\n", uc_priv->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt() - set the minimum number of pages in each of the RX/TX buffers
+ * @dev: The FF-A bus device
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * Set the minimum number of pages in each of the RX/TX buffers in uc_priv
+ *
+ * Return:
+ *
+ * rxtx_min_pages field contains the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	switch (prop_field) {
+	case RXTX_4K:
+		uc_priv->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		uc_priv->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		uc_priv->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		log_err("RX/TX buffer size not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features_hdlr() - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_FEATURES FF-A function to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers() - free the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Free the RX/TX buffers
+ */
+static void ffa_free_rxtx_buffers(struct udevice *dev)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Freeing FF-A RX/TX buffers\n");
+
+	if (uc_priv->pair.rxbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+	}
+
+	if (uc_priv->pair.txbuf) {
+		free(uc_priv->pair.txbuf);
+		uc_priv->pair.txbuf = NULL;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers() - allocate the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ * The size of the memory allocated is the minimum allowed.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(struct udevice *dev)
+{
+	u64 bytes;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Using %lu 4KB page(s) for FF-A RX/TX buffers size\n",
+		  uc_priv->pair.rxtx_min_pages);
+
+	bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 * Assumption: Memory allocated with memalign is always physically contiguous
+	 */
+
+	uc_priv->pair.rxbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.rxbuf) {
+		log_err("failure to allocate RX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A RX buffer at virtual address %p\n", uc_priv->pair.rxbuf);
+
+	uc_priv->pair.txbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.txbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+		log_err("failure to allocate the TX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A TX buffer at virtual address %p\n", uc_priv->pair.txbuf);
+
+	/* Make sure the buffers are cleared before use */
+	memset(uc_priv->pair.rxbuf, 0, bytes);
+	memset(uc_priv->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers_hdlr() - FFA_RXTX_MAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_MAP FF-A function to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	ret = ffa_alloc_rxtx_buffers(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 * no need to convert from virtual to physical
+	 */
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = map_to_sysmem(uc_priv->pair.txbuf),
+			.a2 = map_to_sysmem(uc_priv->pair.rxbuf),
+			.a3 = uc_priv->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		log_debug("FF-A RX/TX buffers mapped\n");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers(dev);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_UNMAP FF-A function to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	log_debug("unmapping FF-A RX/TX buffers\n");
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers(dev);
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer_hdlr() - FFA_RX_RELEASE handler function
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_RX_RELEASE FF-A function to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical() - check whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * Used by ffa_read_partitions_info to search for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+static bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+				   const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info() - read queried partition data
+ * @dev: The FF-A bus device
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * Read the partitions information returned by the FFA_PARTITION_INFO_GET and saves it in uc_priv
+ *
+ * Return:
+ *
+ * uc_priv is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(struct udevice *dev, u32 count,
+				    struct ffa_partition_uuid *part_uuid)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	if (!count) {
+		log_err("no partition detected\n");
+		return -ENODATA;
+	}
+
+	log_debug("Reading FF-A partitions data from the RX buffer\n");
+
+	if (!part_uuid) {
+		/* Querying information of all partitions */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			log_err("partitions data size exceeds the RX buffer size:\n");
+			log_err("    sizes in bytes: data %llu , RX buffer %llu\n",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		uc_priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO);
+		if (!uc_priv->partitions.descs) {
+			log_err("cannot  allocate partitions data buffer\n");
+			return -ENOMEM;
+		}
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			uc_priv->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			log_debug("FF-A partition ID %x : info cached\n",
+				  uc_priv->partitions.descs[desc_idx].info.id);
+		}
+
+		uc_priv->partitions.count = count;
+
+		log_debug("%d FF-A partition(s) found and cached\n", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		/*
+		 * Search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/* Search the current ID in the cached partitions */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < uc_priv->partitions.count;
+			     cached_desc_idx++) {
+				/* Save the UUID */
+				if (uc_priv->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					uc_priv->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info() - invoke FFA_PARTITION_INFO_GET and save partitions data
+ * @dev: The FF-A bus device
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * Execute the FFA_PARTITION_INFO_GET to query the partitions data.
+ * Then, call ffa_read_partitions_info to save the data in uc_priv.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid);
+			if (ret) {
+				log_err("failed reading SP(s) data , err (%d)\n", ret);
+				ffa_release_rx_buffer_hdlr(dev);
+				return -EINVAL;
+			}
+		}
+
+		/* Return the SP count (when querying using a UUID) */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer_hdlr(dev);
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET FF-A function to query the partition information
+ * from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * If the partition(s) matching the UUID found, the partition(s) information and the
+ * number are returned.
+ * If no partition matching the UUID is found in the cached area, a new FFA_PARTITION_INFO_GET
+ * call is issued.
+ * If not done yet, the UUID is updated in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	u32 i;
+	struct ffa_partition_uuid part_uuid = {0};
+	struct ffa_priv *uc_priv;
+	struct ffa_partition_desc *rx_descs;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs) {
+		log_err("no partition installed\n");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		log_err("no UUID provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_count) {
+		log_err("no count argument provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_descs) {
+		log_err("no info argument provided\n");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		log_err("invalid UUID\n");
+		return -EINVAL;
+	}
+
+	log_debug("Searching FF-A partitions using the provided UUID\n");
+
+	*sp_count = 0;
+	*sp_descs = uc_priv->pair.rxbuf;
+	rx_descs = *sp_descs;
+
+	/* Search in the cached partitions */
+	for (i = 0; i < uc_priv->partitions.count; i++)
+		if (ffa_uuid_are_identical(&uc_priv->partitions.descs[i].sp_uuid,
+					   &part_uuid)) {
+			log_debug("FF-A partition ID %x matches the provided UUID\n",
+				  uc_priv->partitions.descs[i].info.id);
+
+			(*sp_count)++;
+			*rx_descs++ = uc_priv->partitions.descs[i];
+			}
+
+	if (!(*sp_count)) {
+		int ret;
+
+		log_debug("No FF-A partition found. Querying framework ...\n");
+
+		ret = ffa_query_partitions_info(dev, &part_uuid, sp_count);
+
+		if (!ret) {
+			log_debug("Number of FF-A partition(s) matching the UUID: %d\n", *sp_count);
+
+			if (*sp_count)
+				ret = ffa_get_partitions_info_hdlr(dev, uuid_str, sp_count,
+								   sp_descs);
+			else
+				ret = -ENODATA;
+		}
+
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info() - Query and saves all secure partitions data
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_PARTITION_INFO_GET FF-A function to query from secure world
+ * all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in uc_priv
+ * and we keep the UUID field empty (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * Called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(struct udevice *dev)
+{
+	return ffa_query_partitions_info(dev, NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Implement FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u64 req_mode, resp_mode;
+	struct ffa_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* No partition installed */
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs)
+		return -ENODEV;
+
+	if (is_smc64) {
+		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+	} else {
+		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = req_mode,
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == resp_mode) {
+		/* Message sent with response extract the return data */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/* FF-A driver operations (used by clients for communicating with FF-A)*/
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Driver operation for FFA_PARTITION_INFO_GET.
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->partition_info_get)
+		return -ENOSYS;
+
+	return ops->partition_info_get(dev, uuid_str, sp_count, sp_descs);
+}
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Driver operation for FFA_MSG_SEND_DIRECT_{REQ,RESP}.
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->sync_send_receive)
+		return -ENOSYS;
+
+	return ops->sync_send_receive(dev, dst_part_id, msg, is_smc64);
+}
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * @dev: The FF-A bus device
+ *
+ * Driver operation for FFA_RXTX_UNMAP.
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_rxtx_unmap(struct udevice *dev)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->rxtx_unmap)
+		return -ENOSYS;
+
+	return ops->rxtx_unmap(dev);
+}
+
+/**
+ * ffa_do_probe() - probing FF-A framework
+ * @dev:	the FF-A bus device (arm_ffa)
+ *
+ * Probing is triggered on demand by clients searching for the uclass.
+ * At probe level the following actions are done:
+ *	- saving the FF-A framework version in uc_priv
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in uc_priv.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_do_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_endpoint_id(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_cache_partitions_info(dev);
+	if (ret) {
+		ffa_unmap_rxtx_buffers_hdlr(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+UCLASS_DRIVER(ffa) = {
+	.name			= "ffa",
+	.id			= UCLASS_FFA,
+	.pre_probe		= ffa_do_probe,
+	.pre_remove		= ffa_unmap_rxtx_buffers_hdlr,
+	.per_device_auto	= sizeof(struct ffa_priv)
+};
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
new file mode 100644
index 0000000000..68df75bd9e
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -0,0 +1,104 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <linux/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * 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 low level SMC assembly function
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * arm_ffa_discover() - perform FF-A discovery
+ * @dev: The Arm FF-A bus device (arm_ffa)
+ * 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:
+ *
+ * true on success. Otherwise, false.
+ */
+static bool arm_ffa_discover(struct udevice *dev)
+{
+	int ret;
+
+	log_info("Arm FF-A framework discovery\n");
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/**
+ * arm_ffa_is_supported() - FF-A bus discovery callback
+ * @invoke_fn: legacy SMC invoke function (not used)
+ *
+ * Perform FF-A discovery by calling arm_ffa_discover().
+ * Discovery is performed by querying the FF-A framework version from
+ * secure world using the FFA_VERSION ABI.
+ *
+ * The FF-A driver is registered as an SMCCC feature driver. So, features discovery
+ * callbacks are called by the PSCI driver (PSCI device is the SMCCC features
+ * root device).
+ *
+ * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
+ * So, the legacy SMC invocation is not used.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static bool arm_ffa_is_supported(void (*invoke_fn)(ulong a0, ulong a1,
+						   ulong a2, ulong a3,
+						   ulong a4, ulong a5,
+						   ulong a6, ulong a7,
+						   struct arm_smccc_res *res))
+{
+	return arm_ffa_discover(NULL);
+}
+
+/* Arm FF-A driver operations */
+
+static const struct ffa_bus_ops 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,
+};
+
+/* Registering the FF-A driver as an SMCCC feature driver */
+
+ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
+	.driver_name = FFA_DRV_NAME,
+	.is_supported = arm_ffa_is_supported,
+};
+
+/* Declaring the FF-A driver under UCLASS_FFA */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.flags		= DM_REMOVE_OS_PREPARE,
+	.ops		= &ffa_ops,
+};
diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
new file mode 100644
index 0000000000..4338f9c9b1
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
@@ -0,0 +1,14 @@
+/* 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/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..db9b1be995
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,213 @@
+/* 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 __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
+ * @a1-4:	32-bit words access to the UUID data
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct ffa_send_direct_data {
+	ulong data0; /* w3/x3 */
+	ulong data1; /* w4/x4 */
+	ulong data2; /* w5/x5 */
+	ulong data3; /* w6/x6 */
+	ulong data4; /* w7/x7 */
+};
+
+struct udevice;
+
+/**
+ * struct ffa_bus_ops - Operations for FF-A
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
+				  u32 *sp_count, struct ffa_partition_desc **sp_descs);
+	int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg,
+				 bool is_smc64);
+	int (*rxtx_unmap)(struct udevice *dev);
+};
+
+#define ffa_get_ops(dev)        ((struct ffa_bus_ops *)(dev)->driver->ops)
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ */
+int ffa_rxtx_unmap(struct udevice *dev);
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The arm_ffa bus device
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev);
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The arm_ffa bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+struct ffa_priv;
+
+/**
+ * ffa_set_smc_conduit() - Set the SMC conduit
+ * @dev: The FF-A bus device
+ *
+ * Selects the SMC conduit by setting the FF-A ABI invoke function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_set_smc_conduit(struct udevice *dev);
+
+#endif
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
new file mode 100644
index 0000000000..d564c33c64
--- /dev/null
+++ b/include/arm_ffa_priv.h
@@ -0,0 +1,246 @@
+/* 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 __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <mapmem.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+
+/* This header is exclusively used by the FF-A Uclass and FF-A driver(s) */
+
+/* Arm FF-A driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* The FF-A SMC function definitions */
+
+#if CONFIG_IS_ENABLED(SANDBOX)
+
+/* Providing Arm SMCCC declarations to sandbox */
+
+/**
+ * struct sandbox_smccc_1_2_regs - emulated SMC call arguments or results
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct sandbox_smccc_1_2_regs {
+	ulong a0;
+	ulong a1;
+	ulong a2;
+	ulong a3;
+	ulong a4;
+	ulong a5;
+	ulong a6;
+	ulong a7;
+	ulong a8;
+	ulong a9;
+	ulong a10;
+	ulong a11;
+	ulong a12;
+	ulong a13;
+	ulong a14;
+	ulong a15;
+	ulong a16;
+	ulong a17;
+};
+
+typedef struct sandbox_smccc_1_2_regs ffa_value_t;
+
+#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))
+
+#else
+/* CONFIG_ARM64 */
+#include <linux/arm-smccc.h>
+typedef struct arm_smccc_1_2_regs ffa_value_t;
+#endif
+
+/* Defining the function pointer type for the function executing the FF-A ABIs */
+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)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR                 = 0x60,
+	FFA_SUCCESS               = 0x61,
+	FFA_INTERRUPT             = 0x62,
+	FFA_VERSION               = 0x63,
+	FFA_FEATURES              = 0x64,
+	FFA_RX_RELEASE            = 0x65,
+	FFA_RXTX_MAP              = 0x66,
+	FFA_RXTX_UNMAP            = 0x67,
+	FFA_PARTITION_INFO_GET    = 0x68,
+	FFA_ID_GET                = 0x69,
+	FFA_RUN                   = 0x6d,
+	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
+	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
+
+	/* To be updated when adding new FFA IDs */
+	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
+	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
+};
+
+enum ffa_abi_errcode {
+	NOT_SUPPORTED = 1,
+	INVALID_PARAMETERS,
+	NO_MEMORY,
+	BUSY,
+	INTERRUPTED,
+	DENIED,
+	RETRY,
+	ABORTED,
+	MAX_NUMBER_FFA_ERR
+};
+
+extern int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR];
+
+/* Container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Hosts the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	void *rxbuf; /* Virtual address returned by memalign */
+	void *txbuf; /* Virtual address returned by memalign */
+	size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */
+};
+
+struct ffa_partition_desc;
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * Contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* Virtual address */
+};
+
+/**
+ * struct ffa_priv - the driver private data structure
+ *
+ * @fwk_version:	FF-A framework version
+ * @emul:	FF-A sandbox emulator
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ *
+ * The device private data structure containing all the
+ * data read from secure world.
+ */
+struct ffa_priv {
+	u32 fwk_version;
+	struct udevice *emul;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+};
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev);
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 307ad6931c..3c6af2e3d2 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,11 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -57,6 +62,7 @@ enum uclass_id {
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_EXTCON,		/* External Connector Class */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v18 5/9] arm_ffa: introduce sandbox FF-A support
  2023-08-03 16:03                                                                                                                                                                             ` [PATCH v18 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                 ` (3 preceding siblings ...)
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 4/9] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-08-03 16:03                                                                                                                                                                               ` Abdellatif El Khlifi
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 6/9] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                                                                                                                                                                 ` (3 subsequent siblings)
  8 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-03 16:03 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: abdellatif.elkhlifi, achin.gupta, jens.wiklander, nd, sjg, trini,
	u-boot, Heinrich Schuchardt

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>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove reparenting by making the emulator parent of the FF-A device in the DT
* add invoke_ffa_fn()
* address nits

v11:

* rename ffa_try_discovery() to sandbox_ffa_discover()
* rename sandbox_ffa_query_core_state() to sandbox_query_ffa_emul_state()
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device

v10:

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

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

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

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

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

v1: introduce the sandbox driver

 MAINTAINERS                                   |   3 +-
 arch/sandbox/dts/sandbox.dtsi                 |   9 +
 arch/sandbox/dts/test.dts                     |   8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |  72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        | 121 +++
 configs/sandbox64_defconfig                   |   1 +
 configs/sandbox_defconfig                     |   1 +
 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, 1081 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 4fd5768de0..63cf37290c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,10 +269,11 @@ 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:	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/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..96b5404991 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1820,6 +1820,14 @@
 	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..72ea3d21ab 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -260,3 +260,4 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 1ec44d5b33..8269bec879 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -344,3 +344,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index df18948774..792898321a 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.
@@ -203,6 +206,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
+
 Example of boot logs with FF-A enabled
 --------------------------------------
 
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 9200c8028b..fc668c109d 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
 	select LIB_UUID
 	select DEVRES
 	help
@@ -32,5 +32,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


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v18 6/9] arm_ffa: introduce sandbox test cases for UCLASS_FFA
  2023-08-03 16:03                                                                                                                                                                             ` [PATCH v18 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                 ` (4 preceding siblings ...)
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 5/9] arm_ffa: introduce sandbox " Abdellatif El Khlifi
@ 2023-08-03 16:03                                                                                                                                                                               ` Abdellatif El Khlifi
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 7/9] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                                                                                                                                                                 ` (2 subsequent siblings)
  8 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-03 16:03 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: abdellatif.elkhlifi, achin.gupta, jens.wiklander, nd, sjg, trini,
	u-boot, Heinrich Schuchardt

Add functional test cases for the FF-A support

These tests rely on the FF-A sandbox emulator and FF-A
sandbox driver which help in inspecting the FF-A communication.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove use of dscvry_info
* drop use of calloc when querying SPs
* address nits

v11:

* drop unmapping test (taken care of by the DM when removing the device)
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT
* address nits

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

v8:

  * update partition_info_get() second argument to be an SP count
  * pass NULL device pointer to the FF-A bus discovery and operations

v7: set the tests to use 64-bit direct messaging

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

v1: introduce sandbox tests

 MAINTAINERS            |   1 +
 doc/arch/arm64.ffa.rst |   1 +
 test/dm/Makefile       |   3 +-
 test/dm/ffa.c          | 261 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 265 insertions(+), 1 deletion(-)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 63cf37290c..b6d7263010 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -274,6 +274,7 @@ F:	arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
 F:	doc/arch/arm64.ffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 792898321a..71606373f9 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -37,6 +37,7 @@ The U-Boot FF-A support provides the following parts:
   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.
+- Sandbox FF-A test cases.
 
 FF-A and SMC specifications
 -------------------------------------------
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 3799b1ae8f..7ed00733c1 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
-# Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -92,6 +92,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..6912666bb4
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <console.h>
+#include <dm.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <asm/sandbox_arm_ffa_priv.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Functional tests for the UCLASS_FFA */
+
+static int check_fwk_version(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	struct ffa_sandbox_data func_data;
+	u32 fwk_version = 0;
+
+	func_data.data0 = &fwk_version;
+	func_data.data0_size = sizeof(fwk_version);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_VERSION, &func_data));
+	ut_asserteq(uc_priv->fwk_version, fwk_version);
+
+	return 0;
+}
+
+static int check_endpoint_id(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_asserteq(0, uc_priv->id);
+
+	return 0;
+}
+
+static int check_rxtxbuf(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assertnonnull(uc_priv->pair.rxbuf);
+	ut_assertnonnull(uc_priv->pair.txbuf);
+
+	return 0;
+}
+
+static int check_features(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assert(uc_priv->pair.rxtx_min_pages == RXTX_4K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_16K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_64K);
+
+	return 0;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+		ut_asserteq(1, rxbuf_mapped);
+		break;
+	case FFA_RXTX_UNMAP:
+		ut_asserteq(0, rxbuf_mapped);
+		break;
+	default:
+		ut_assert(false);
+	}
+
+	return 0;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	ut_asserteq(0, rxbuf_owned);
+
+	return 0;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg;
+	u8 cnt;
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]);
+
+	return 0;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct unit_test_state *uts)
+{
+	struct ffa_partition_desc *descs;
+	u32 count, i, j, valid_sps = 0;
+	struct udevice *dev;
+	struct ffa_sandbox_data func_data;
+	struct ffa_partitions *partitions;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get from the driver the count and information of the SPs matching the UUID */
+	ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, &descs));
+
+	/* Make sure the count is correct */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+
+	/* SPs found , verify the partitions information */
+
+	func_data.data0 = &partitions;
+	func_data.data0_size = sizeof(struct ffa_partitions *);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_PARTITION_INFO_GET, &func_data));
+
+	for (i = 0; i < count ; i++) {
+		for (j = 0;
+		     j < partitions->count;
+		     j++) {
+			if (descs[i].info.id ==
+			   partitions->descs[j].info.id) {
+				valid_sps++;
+				ut_asserteq_mem(&descs[i],
+						&partitions->descs[j],
+						sizeof(struct ffa_partition_desc));
+				/* Send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(descs[i].info.id, uts);
+			}
+		}
+	}
+
+	/* Verify expected partitions found in the emulated secure world */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, valid_sps);
+
+	return 0;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	struct ffa_sandbox_data func_data;
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	struct udevice *dev;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Test FFA_VERSION */
+	check_fwk_version(uc_priv, uts);
+
+	/* Test FFA_ID_GET */
+	check_endpoint_id(uc_priv, uts);
+
+	/* Test FFA_FEATURES */
+	check_features(uc_priv, uts);
+
+	/*  Test RX/TX buffers */
+	check_rxtxbuf(uc_priv, uts);
+
+	/* Test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	sandbox_query_ffa_emul_state(FFA_RXTX_MAP, &func_data);
+	check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc1_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data);
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc2_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data));
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg;
+	int ret;
+	u32 count;
+	u16 part_id = 0;
+	struct udevice *dev;
+	struct ffa_partition_desc *descs = NULL;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Query partitions count using  invalid arguments */
+	ret = ffa_partition_info_get(dev, NULL, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, NULL);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID  string */
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid_str, &count, &descs);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, &descs);
+	ut_asserteq(0, count);
+
+	/* Query partitions data using a valid UUID */
+	count = 0;
+	ut_assertok(ffa_partition_info_get(dev, valid_svc_uuid, &count, &descs));
+	/* Make sure partitions are detected */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+	ut_assertnonnull(descs);
+
+	/* Send data to an invalid partition */
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Send data to a valid partition */
+	part_id = uc_priv->partitions.descs[0].info.id;
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v18 7/9] arm_ffa: introduce armffa command
  2023-08-03 16:03                                                                                                                                                                             ` [PATCH v18 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                 ` (5 preceding siblings ...)
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 6/9] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-08-03 16:03                                                                                                                                                                               ` Abdellatif El Khlifi
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 8/9] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 9/9] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  8 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-03 16:03 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: abdellatif.elkhlifi, achin.gupta, jens.wiklander, nd, sjg, trini,
	u-boot, Heinrich Schuchardt

Provide armffa command showcasing the use of the U-Boot FF-A support

armffa is a command showcasing how to invoke FF-A operations.
This provides a guidance to the client developers on how to
call the FF-A bus interfaces. The command also allows to gather secure
partitions information and ping these  partitions. The command is also
helpful in testing the communication with secure partitions.

For more details please refer to the command documentation [1].

A Sandbox test is provided for the armffa command.

[1]: doc/usage/cmd/armffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v18:

Simon:

* Combining the commits of the command and the test case

v15:

Simon:

* armffa.c : integrate PHYS_ADDR_LN

v14:

Ilias:

* address nits
* in do_ffa_ping() reject the SP ID if it's 0
* use PHYS_ADDR_LN in formatting the physical addresses

v12:

* add subcommands argument checks
* usage documentation: update command return codes
* remove calloc when querying SPs
* address nits

v11:

* use U_BOOT_CMD_WITH_SUBCMDS
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* address nits

v9:

* remove manual FF-A discovery and use DM
* use DM class APIs to probe and interact with the FF-A bus
* add doc/usage/cmd/armffa.rst

v8:

* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* adapt do_ffa_dev_list() following the recent update on
  uclass_first_device/uclass_next_device functions (they return void now)
* set armffa command to use 64-bit direct messaging

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

 MAINTAINERS                      |   3 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   1 +
 cmd/armffa.c                     | 202 +++++++++++++++++++++++++++++++
 doc/arch/arm64.ffa.rst           |   9 ++
 doc/usage/cmd/armffa.rst         |  94 ++++++++++++++
 doc/usage/index.rst              |   1 +
 drivers/firmware/arm-ffa/Kconfig |   1 +
 test/cmd/Makefile                |   2 +
 test/cmd/armffa.c                |  33 +++++
 10 files changed, 356 insertions(+)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/usage/cmd/armffa.rst
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index b6d7263010..bd3dba3d95 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -271,9 +271,12 @@ 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:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/cmd/Kconfig b/cmd/Kconfig
index c1941849f9..da8569b417 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -935,6 +935,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the FF-A support
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index 6c37521b4e..7d20a85a46 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,7 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_2048) += 2048.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..7e6eafc03a
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,202 @@
+// 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 <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+#include <asm/io.h>
+
+/* Select the right physical address formatting according to the platform */
+#ifdef CONFIG_PHYS_64BIT
+#define PhysAddrLength "ll"
+#else
+#define PhysAddrLength ""
+#endif
+#define PHYS_ADDR_LN "%" PhysAddrLength "x"
+
+/**
+ * ffa_get_dev() - Return the FF-A device
+ * @devp:	pointer to the FF-A device
+ *
+ * Search for the FF-A device.
+ *
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_dev(struct udevice **devp)
+{
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, devp);
+	if (ret) {
+		log_err("Cannot find FF-A bus device\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * do_ffa_getpart() - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query a secure partition information. The secure partition UUID is provided
+ * as an argument. The function uses the arm_ffa driver
+ * partition_info_get operation which implements FFA_PARTITION_INFO_GET
+ * ABI to retrieve the data. The input UUID string is expected to be in big
+ * endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	u32 i;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+
+	ret = ffa_partition_info_get(dev, argv[1], &count, &descs);
+	if (ret) {
+		log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	/* SPs found , show the partition information */
+	for (i = 0; i < count ; i++) {
+		log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
+			 descs[i].info.id,
+			 descs[i].info.exec_ctxt,
+			 descs[i].info.properties);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_ffa_ping() - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Send data to a secure partition. The secure partition UUID is provided
+ * as an argument. Use the arm_ffa driver sync_send_receive operation
+ * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	part_id = strtoul(argv[1], NULL, 16);
+	if (!part_id) {
+		log_err("Partition ID can not be 0\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	if (!ret) {
+		u8 cnt;
+
+		log_info("SP response:\n[LSB]\n");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			log_info("%llx\n", ((u64 *)&msg)[cnt]);
+		return CMD_RET_SUCCESS;
+	}
+
+	log_err("Sending direct request error (%d)\n", ret);
+	return CMD_RET_FAILURE;
+}
+
+/**
+ *do_ffa_devlist() - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query the device belonging to the UCLASS_FFA
+ * class.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",
+		 dev->name,
+		 map_to_sysmem(dev),
+		 dev->driver->name,
+		 map_to_sysmem(dev->driver->ops));
+
+	return CMD_RET_SUCCESS;
+}
+
+static char armffa_help_text[] =
+	"getpart <partition UUID>\n"
+	"       - lists the partition(s) info\n"
+	"ping <partition ID>\n"
+	"       - sends a data pattern to the specified partition\n"
+	"devlist\n"
+	"       - displays information about the FF-A device/driver\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
+			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
+			U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping),
+			U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist));
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 71606373f9..325fb80346 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -120,6 +120,8 @@ At this stage the FF-A bus is registered with the DM and can be interacted with
 the DM APIs.
 
 Clients are able to probe then use the FF-A bus by calling uclass_first_device().
+Please refer to the armffa command implementation as an example of how to probe
+and interact with the FF-A bus.
 
 When calling uclass_first_device(), the FF-A driver is probed and ends up calling
 ffa_do_probe() provided by the Uclass which does the following:
@@ -219,6 +221,13 @@ Relationship between the sandbox emulator and the FF-A device
    ffa_emul      0  [ + ]   sandbox_ffa_emul      `-- arm-ffa-emul
     ffa                  0  [    ]   sandbox_arm_ffa               `-- sandbox-arm-ffa
 
+The armffa command
+-----------------------------------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke the driver operations.
+
+Please refer the command documentation at :doc:`../usage/cmd/armffa`
+
 Example of boot logs with FF-A enabled
 --------------------------------------
 
diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
new file mode 100644
index 0000000000..13fa90c129
--- /dev/null
+++ b/doc/usage/cmd/armffa.rst
@@ -0,0 +1,94 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+
+armffa command
+==============
+
+Synopsis
+--------
+
+::
+
+   armffa [sub-command] [arguments]
+
+   sub-commands:
+
+        getpart [partition UUID]
+
+            lists the partition(s) info
+
+        ping [partition ID]
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays information about the FF-A device/driver
+
+Description
+-----------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
+
+The command also allows to gather secure partitions information and ping these  partitions.
+
+The command is also helpful in testing the communication with secure partitions.
+
+Example
+-------
+
+The following examples are run on Corstone-1000 platform.
+
+* ping
+
+::
+
+   corstone1000# armffa ping 0x8003
+   SP response:
+   [LSB]
+   fffffffe
+   0
+   0
+   0
+   0
+
+* ping (failure case)
+
+::
+
+   corstone1000# armffa ping 0
+   Sending direct request error (-22)
+
+* getpart
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
+   Partition: id = 8003 , exec_ctxt 1 , properties 3
+
+* getpart (failure case)
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221
+   INVALID_PARAMETERS: Unrecognized UUID
+   Failure in querying partitions count (error code: -22)
+
+* devlist
+
+::
+
+   corstone1000# armffa devlist
+   device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98
+
+Configuration
+-------------
+
+The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
+
+Return value
+------------
+
+The return value $? is 0 (true) on success, 1 (false) on failure.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 388e59f173..e462de2806 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -22,6 +22,7 @@ Shell commands
 
    cmd/acpi
    cmd/addrmap
+   cmd/armffa
    cmd/askenv
    cmd/base
    cmd/bdinfo
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index fc668c109d..d75f8b53fd 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
 	depends on DM && (ARM64 || SANDBOX)
 	select ARM_SMCCC if !SANDBOX
 	select ARM_SMCCC_FEATURES if !SANDBOX
+	imply CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index a3cf983739..6e3d7e919e 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -24,6 +25,7 @@ obj-$(CONFIG_CMD_SEAMA) += seama.o
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_CMD_READ) += rw.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o
 endif
 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
 obj-$(CONFIG_CMD_WGET) += wget.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..9a44a397e8
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * 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 <string.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	/* armffa ping <ID> */
+	ut_assertok(run_commandf("armffa ping 0x%x", SANDBOX_SP1_ID));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return 0;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v18 8/9] arm_ffa: efi: introduce FF-A MM communication
  2023-08-03 16:03                                                                                                                                                                             ` [PATCH v18 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                 ` (6 preceding siblings ...)
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 7/9] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-08-03 16:03                                                                                                                                                                               ` Abdellatif El Khlifi
  2023-08-03 17:13                                                                                                                                                                                 ` Tom Rini
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 9/9] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
  8 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-03 16:03 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: abdellatif.elkhlifi, achin.gupta, jens.wiklander, nd, sjg, trini,
	u-boot, Gowtham Suresh Kumar

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

MM communication protocol supports FF-A 64-bit direct messaging.

We tested the FF-A MM communication on the Corstone-1000 platform.

We ran the UEFI SCT test suite containing EFI setVariable, getVariable and
getNextVariable tests which involve FF-A MM communication and all tests
are passing with the current changes.

We made the SCT test reports (part of the ACS results) public following the
latest Corstone-1000 platform software release. Please find the test
reports at [1].

[1]: https://gitlab.arm.com/arm-reference-solutions/arm-reference-solutions-test-report/-/tree/master/embedded-a/corstone1000/CORSTONE1000-2023.06/acs_results_fpga.zip

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v18:

Ilias, Tom:

* drop the use of configs for the shared MM buffer, put back #ifdefs instead
* add test information to the commit log

v17:

* show a debug message rather than an error when FF-A is not detected

v16:

* lib/efi_loader/Kconfig:
   rather than automatically selecting OPTEE and ARM_FFA_TRANSPORT configs by
   EFI_MM_COMM_TEE, set them as dependencies (Otherwise FF-A will be automatically
   enabled for boards that don't need it).

v15:

Simon:

* replace FFA_SHARED_MM_BUFFER_* defines with configs

v14:

Ilias:

* drop truncating var_payload->size when using FF-A
* map the MM SP return codes to errnos

v13:

* remove FF-A and Optee ifdefs

v12:

* drop use of calloc when querying SPs
* address nits

v11:

* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* addressing nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* addressing nits

v9: align how FF-A is used with FF-A discovery through DM

v8:

* isolate the compilation choices between FF-A and OP-TEE
* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make mm_sp_svc_uuid static
* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
* improve use of unmap_sysmem() in ffa_mm_communicate()

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

 include/mm_communication.h        |  17 ++
 lib/efi_loader/Kconfig            |  42 ++++-
 lib/efi_loader/efi_variable_tee.c | 282 +++++++++++++++++++++++++++++-
 3 files changed, 335 insertions(+), 6 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..f38f1a5344 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,9 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *    Authors:
+ *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +16,11 @@
 
 #include <part_efi.h>
 
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+#endif
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
@@ -248,4 +256,13 @@ struct smm_variable_var_check_property {
 	u16                       name[];
 };
 
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+/* supported MM transports */
+enum mm_comms_select {
+	MM_COMMS_UNDEFINED,
+	MM_COMMS_FFA,
+	MM_COMMS_OPTEE
+};
+#endif
+
 #endif /* _MM_COMMUNICATION_H_ */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c5835e6ef6..19e51bf503 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,53 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
+	bool "UEFI variables storage service via the trusted world"
 	depends on OPTEE
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
+config FFA_SHARED_MM_BUF_SIZE
+	int "Memory size of the shared MM communication buffer"
+	default 0
+	depends on EFI_MM_COMM_TEE
+	help
+	  This defines the size in bytes of the memory area reserved for the shared
+	  buffer used for communication between the MM feature in U-Boot and
+	  the MM SP in secure world.
+	  The size of the memory region must be a multiple of the size of the maximum
+	  translation granule size that is specified in the ID_AA64MMFR0_EL1 System register.
+	  It is assumed that the MM SP knows the size of the shared MM communication buffer.
+
+config FFA_SHARED_MM_BUF_OFFSET
+	int "Data offset in the shared MM communication buffer"
+	default 0
+	depends on EFI_MM_COMM_TEE
+	help
+	  This defines the offset in bytes of the data read or written to in the shared
+	  buffer by the MM SP.
+
+config FFA_SHARED_MM_BUF_ADDR
+	hex "Define the address of the shared MM communication buffer"
+	default 0x0
+	depends on EFI_MM_COMM_TEE
+	help
+	  This defines the address of the shared MM communication buffer
+	  used for communication between the MM feature in U-Boot and
+	  the MM SP in secure world.
+	  It is assumed that the MM SP knows the address of the shared MM communication buffer.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..07bf64f270 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,16 +4,50 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  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>
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+#include <arm_ffa.h>
+#endif
+#include <cpu_func.h>
+#include <dm.h>
 #include <efi.h>
 #include <efi_api.h>
 #include <efi_loader.h>
 #include <efi_variable.h>
-#include <tee.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <mm_communication.h>
+#include <tee.h>
+
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+#ifndef FFA_SHARED_MM_BUFFER_SIZE
+#define FFA_SHARED_MM_BUFFER_SIZE SZ_4K
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_OFFSET
+#define FFA_SHARED_MM_BUFFER_OFFSET 0
+#endif
+
+#ifndef FFA_SHARED_MM_BUFFER_ADDR
+#define FFA_SHARED_MM_BUFFER_ADDR 0x02000000UL
+#endif
+
+/* MM return codes */
+#define MM_SUCCESS (0)
+#define MM_NOT_SUPPORTED (-1)
+#define MM_INVALID_PARAMETER (-2)
+#define MM_DENIED (-3)
+#define MM_NO_MEMORY (-5)
+
+static const char *mm_sp_svc_uuid = MM_SP_UUID;
+static u16 mm_sp_id;
+#endif
 
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
@@ -144,12 +178,238 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 	return ret;
 }
 
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+/**
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notify the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
+		return ret;
+	}
+
+	msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */
+
+	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
+	if (ret)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	switch (sp_event_ret) {
+	case MM_SUCCESS:
+		ret = 0;
+		break;
+	case MM_NOT_SUPPORTED:
+		ret = -EINVAL;
+		break;
+	case MM_INVALID_PARAMETER:
+		ret = -EPERM;
+		break;
+	case MM_DENIED:
+		ret = -EACCES;
+		break;
+	case MM_NO_MEMORY:
+		ret = -EBUSY;
+		break;
+	default:
+		ret = -EACCES;
+	}
+
+	return ret;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
+		return ret;
+	}
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, &descs);
+	if (ret) {
+		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
+		return ret;
+	}
+
+	/* MM SPs found , use the first one */
+
+	mm_sp_id = descs[0].info.id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	return 0;
+}
+
+/**
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	efi_status_t efi_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()) {
+		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+
+	switch (ffa_ret) {
+	case 0: {
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		efi_ret = EFI_SUCCESS;
+		break;
+	}
+	case -EINVAL:
+		efi_ret = EFI_DEVICE_ERROR;
+		break;
+	case -EPERM:
+		efi_ret = EFI_INVALID_PARAMETER;
+		break;
+	case -EACCES:
+		efi_ret = EFI_ACCESS_DENIED;
+		break;
+	case -EBUSY:
+		efi_ret = EFI_OUT_OF_RESOURCES;
+		break;
+	default:
+		efi_ret = EFI_ACCESS_DENIED;
+	}
+
+	unmap_sysmem(virt_shared_buf);
+	return efi_ret;
+}
+
+/**
+ * get_mm_comms() - detect the available MM transport
+ *
+ * Make sure the FF-A bus is probed successfully
+ * which means FF-A communication with secure world works and ready
+ * for use.
+ *
+ * If FF-A bus is not ready, use OPTEE comms.
+ *
+ * Return:
+ *
+ * MM_COMMS_FFA or MM_COMMS_OPTEE
+ */
+static enum mm_comms_select get_mm_comms(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_debug("EFI: Cannot find FF-A bus device, trying Optee comms\n");
+		return MM_COMMS_OPTEE;
+	}
+
+	return MM_COMMS_FFA;
+}
+#endif
+
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
@@ -157,12 +417,24 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	efi_status_t ret;
 	struct efi_mm_communicate_header *mm_hdr;
 	struct smm_variable_communicate_header *var_hdr;
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+	enum mm_comms_select mm_comms;
+#endif
 
 	dsize += MM_COMMUNICATE_HEADER_SIZE + MM_VARIABLE_COMMUNICATE_SIZE;
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+	mm_comms = get_mm_comms();
+	if (mm_comms == MM_COMMS_FFA)
+		ret = ffa_mm_communicate(comm_buf, dsize);
+	else
+		ret = optee_mm_communicate(comm_buf, dsize);
+#else
+		ret = optee_mm_communicate(comm_buf, dsize);
+#endif
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -697,7 +969,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v18 9/9] arm_ffa: efi: corstone1000: enable MM communication
  2023-08-03 16:03                                                                                                                                                                             ` [PATCH v18 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                 ` (7 preceding siblings ...)
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 8/9] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-08-03 16:03                                                                                                                                                                               ` Abdellatif El Khlifi
  2023-08-03 17:14                                                                                                                                                                                 ` Tom Rini
  8 siblings, 1 reply; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-03 16:03 UTC (permalink / raw)
  To: ilias.apalodimas
  Cc: abdellatif.elkhlifi, achin.gupta, jens.wiklander, nd, sjg, trini, u-boot

turn on EFI MM communication

On Corstone-1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

Changes made are generated using savedefconfig.

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>

---

Changelog:
===============

v18:

Ilias, Tom:

* drop use of CONFIG_FFA_SHARED_MM_BUF_*

v17:

* use savedefconfig to generate corstone1000_defconfig with FF-A MM comms enabled

v16:

* configs/corstone1000_defconfig:
   enable MM communication by setting the configs: ARM_FFA_TRANSPORT, OPTEE, TEE

v15:

Simon:

* use CONFIG_FFA_SHARED_MM_BUF_* configs in place of FFA_SHARED_MM_BUFFER_*

v13:

* remove FF-A config in the defconfig
   (because it's enabled automatically by CONFIG_EFI_MM_COMM_TEE)

v9:

* update copyright string

v8:

* drop OP-TEE configs from Corstone-1000 defconfig

v7:

* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
  FFA_SHARED_MM_BUFFER_OFFSET
* update FFA_SHARED_MM_BUFFER_ADDR value

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

 configs/corstone1000_defconfig | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index a8a79fd105..59ce1ec15c 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -28,12 +28,10 @@ CONFIG_CMD_FWU_METADATA=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_SYS_BOOTM_LEN=0x800000
 # CONFIG_CMD_XIMG is not set
-CONFIG_CMD_NVMXIP=y
 CONFIG_CMD_GPT=y
 # CONFIG_RANDOM_UUID is not set
 CONFIG_CMD_LOADM=y
 # CONFIG_CMD_LOADS is not set
-CONFIG_CMD_MMC=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NFS is not set
@@ -45,8 +43,7 @@ CONFIG_OF_CONTROL=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_REGMAP=y
-CONFIG_FWU_MDATA=y
-CONFIG_FWU_MDATA_GPT_BLK=y
+CONFIG_ARM_FFA_TRANSPORT=y
 CONFIG_MISC=y
 # CONFIG_MMC is not set
 CONFIG_NVMXIP_QSPI=y
@@ -59,9 +56,12 @@ CONFIG_DM_RTC=y
 CONFIG_RTC_EMULATION=y
 CONFIG_DM_SERIAL=y
 CONFIG_SYSRESET=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760=y
+CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
 CONFIG_EFI_CAPSULE_ON_DISK=y
 CONFIG_EFI_IGNORE_OSINDICATIONS=y
 CONFIG_FWU_MULTI_BANK_UPDATE=y
-CONFIG_ERRNO_STR=y
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v18 8/9] arm_ffa: efi: introduce FF-A MM communication
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 8/9] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-08-03 17:13                                                                                                                                                                                 ` Tom Rini
  0 siblings, 0 replies; 478+ messages in thread
From: Tom Rini @ 2023-08-03 17:13 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: ilias.apalodimas, achin.gupta, jens.wiklander, nd, sjg, u-boot,
	Gowtham Suresh Kumar

[-- Attachment #1: Type: text/plain, Size: 823 bytes --]

On Thu, Aug 03, 2023 at 05:03:49PM +0100, Abdellatif El Khlifi wrote:

[snip]
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index c5835e6ef6..19e51bf503 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
[snip]
> +config FFA_SHARED_MM_BUF_SIZE
> +	int "Memory size of the shared MM communication buffer"
> +	default 0

Remove the default.

> +	depends on EFI_MM_COMM_TEE

This should be EFI_MM_COMM_TEE && ARM_FFA_TRANSPORT

[snip]
> +config FFA_SHARED_MM_BUF_OFFSET
> +	int "Data offset in the shared MM communication buffer"
> +	default 0
> +	depends on EFI_MM_COMM_TEE

Same.

[snip]
> +config FFA_SHARED_MM_BUF_ADDR
> +	hex "Define the address of the shared MM communication buffer"
> +	default 0x0
> +	depends on EFI_MM_COMM_TEE

Same.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v18 9/9] arm_ffa: efi: corstone1000: enable MM communication
  2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 9/9] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
@ 2023-08-03 17:14                                                                                                                                                                                 ` Tom Rini
  2023-08-04  9:22                                                                                                                                                                                   ` Abdellatif El Khlifi
  2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
  0 siblings, 2 replies; 478+ messages in thread
From: Tom Rini @ 2023-08-03 17:14 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: ilias.apalodimas, achin.gupta, jens.wiklander, nd, sjg, u-boot

[-- Attachment #1: Type: text/plain, Size: 778 bytes --]

On Thu, Aug 03, 2023 at 05:03:50PM +0100, Abdellatif El Khlifi wrote:

> turn on EFI MM communication
> 
> On Corstone-1000 platform MM communication between u-boot
> and the secure world (Optee) is done using the FF-A bus.
> 
> Changes made are generated using savedefconfig.
> 
> 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>
> 
> ---
> 
> Changelog:
> ===============
> 
> v18:
> 
> Ilias, Tom:
> 
> * drop use of CONFIG_FFA_SHARED_MM_BUF_*

Why?  What was wrong before was what I commented on still being wrong in
8/9, this part was fine.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v18 9/9] arm_ffa: efi: corstone1000: enable MM communication
  2023-08-03 17:14                                                                                                                                                                                 ` Tom Rini
@ 2023-08-04  9:22                                                                                                                                                                                   ` Abdellatif El Khlifi
  2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
  1 sibling, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-04  9:22 UTC (permalink / raw)
  To: Tom Rini; +Cc: ilias.apalodimas, nd, u-boot

Hi Tom,

> > Changelog:
> > ===============
> > 
> > v18:
> > 
> > Ilias, Tom:
> > 
> > * drop use of CONFIG_FFA_SHARED_MM_BUF_*
> 
> Why?  What was wrong before was what I commented on still being wrong in
> 8/9, this part was fine.
> 

I thought when we decided to bring back the #ifdefs the buffer macros are also
to be brought back.

Well, I'll keep CONFIG_FFA_SHARED_MM_BUF_*.

Cheers


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v19 0/9] introduce Arm FF-A support
  2023-08-03 17:14                                                                                                                                                                                 ` Tom Rini
  2023-08-04  9:22                                                                                                                                                                                   ` Abdellatif El Khlifi
@ 2023-08-04 13:33                                                                                                                                                                                   ` Abdellatif El Khlifi
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 1/9] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
                                                                                                                                                                                                       ` (10 more replies)
  1 sibling, 11 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-04 13:33 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, sjg, u-boot, Rob Herring, Drew Reed,
	Xueliang Zhong

Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].

FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
communicate with each other. A partition could be a VM in the Normal or Secure world, an
application in S-EL0, or a Trusted OS in S-EL1.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

   => dm tree

    Class     Index  Probed  Driver                Name
   -----------------------------------------------------------
   ...
    firmware      0  [ + ]   psci                      |-- psci
    ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
   ...

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

This implementation of the specification provides support for Aarch64.

The FF-A driver uses the SMC ABIs defined by the FF-A specification to:

    - Discover the presence of secure partitions (SPs) of interest
    - Access an SP's service through communication protocols
      (e.g: EFI MM communication protocol)

The FF-A support provides the following features:

    - Being generic by design and can be used by any Arm 64-bit platform
    - FF-A support can be compiled and used without EFI
    - Support for SMCCCv1.2 x0-x17 registers
    - Support for SMC32 calling convention
    - Support for 32-bit and 64-bit FF-A direct messaging
    - Support for FF-A MM communication (compatible with EFI boot time)
    - Enabling FF-A and MM communication in Corstone1000 platform as a use case
    - 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.
    - Sandbox FF-A test cases.
    - A new command called armffa is provided as an example of how to access the
      FF-A bus

For more details about the FF-A support please refer to [B] and refer to [C] for
how to use the armffa command.

Please find at [D] an example of the expected boot logs when enabling
FF-A support for a platform. In this example the platform is
Corstone1000. But it can be any Arm 64-bit platform.

Changelog of changes:
===========================

v19:

Tom:

* use CONFIG_FFA_SHARED_MM_BUF_* in place of macros

v18: [18]

Ilias, Tom:

* drop the use of configs for the shared MM buffer, put back #ifdefs instead
* add test information to the MM comms commit message

v17: [17]

Ilias:

* show a debug message rather than an error when FF-A is not detected

Tom:

* use savedefconfig to generate corstone1000_defconfig with FF-A MM comms enabled

v16: [16]

Tom:

* lib/efi_loader/Kconfig:
   rather than automatically selecting OPTEE and ARM_FFA_TRANSPORT configs by
   EFI_MM_COMM_TEE, set them as dependencies (Otherwise FF-A will be automatically
   enabled for boards that don't need it).

* configs/corstone1000_defconfig:
   enable MM communication by setting the configs: ARM_FFA_TRANSPORT, OPTEE, TEE

v15: [15]

Simon:

* drop commit "log: select physical address formatting in a generic way",
   this will be sent as a follow-up commit independently from this patchset
* armffa.c : integrate PHYS_ADDR_LN
* replace FFA_SHARED_MM_BUFFER_* defines with configs

v14: [14]

Simon:

    * add to log.h a generic physical address formatting

Ilias:

    * armffa command: in do_ffa_ping() reject the SP ID if it's 0
    * MM comms: drop truncating var_payload->size when using FF-A
    * MM comms: map the MM SP return codes to errnos
    * address nits

v13: [13]

Ilias:
    * remove FF-A and Optee ifdefs in efi_variable_tee.c
    * doc minor change: specify in the readme that the user
       should call ffa_rxtx_unmap() driver operation to unmap
       the RX/TX buffers on demand.

v12: [12]

* remove the global variable (dscvry_info), use uc_priv instead
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* remove reparenting by making the sandbox emulator parent of the FF-A device in the DT
* improve argument checks for the armffa command
* address nits

v11: [11]

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* use U_BOOT_CMD_WITH_SUBCMDS for armffa command
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device
* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* use ut_asserteq_mem() in uuid_str_to_le_bin test case
* address nits

v10: [10]

* provide the FF-A driver operations through the Uclass (arm-ffa-uclass.c)
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c renamed from core.c)
* split the FF-A sandbox support into an emulator (ffa-emul-uclass.c) and a driver (sandbox_ffa.c)
* use the FF-A driver Uclass operations by clients (armffa command, tests, MM comms)
* use uclass_first_device to search and probe the FF-A device (whether it is on Arm or on sandbox)
* address nits

v9: [9]

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding
* align FF-A sandbox driver with FF-A discovery through DM
* use DM class APIs to probe and interact with the FF-A bus (in FF-A MM comms,  armffa command, sandbox tests)
* add documentation for the armffa command: doc/usage/cmd/armffa.rst
* introduce testcase for uuid_str_to_le_bin

v8: [8]

* pass the FF-A bus device to the bus operations
* isolate the compilation choices between FF-A and OP-TEE
* drop OP-TEE configs from Corstone-1000 defconfig
* make ffa_get_partitions_info() second argument to be an SP count in both
  modes

v7: [7]

* add support for 32-bit direct messaging (now we have 32-bit and 64-bit support)
* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v6: [6]

* remove clearing x0-x17 registers after SMC calls
* drop use of EFI runtime support for FF-A (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* add FF-A runtime discovery at MM communication level
* update the documentation and move it to doc/arch/arm64.ffa.rst

v5: [5]

* move changelogs in each commit to the changes section

v4: [4]

* add FF-A support README (doc/README.ffa.drv)
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log
* align sandbox driver and tests with the new FF-A driver interfaces
 and new way of error handling
* use the new FF-A driver interfaces for MM communication
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* moving the FF-A driver work to drivers/firmware/arm-ffa
* improving features discovery in FFA_FEATURES
* add remove/unbind functions to the FF-A core device
* improve how the driver behaves when bus discovery is done more than
  once
* move clearing x0-x17 registers code into a new macro like done in
   the linux kernel
* enable EFI MM communication for the Corstone1000 platform

v3: [3]

* port x0-x17 registers support from linux kernel as defined by
   SMCCCv1.2
* align the interfaces of the u-boot FF-A driver with those in the linux
   FF-A driver
* remove the FF-A helper layer
* make the u-boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to
   EFI runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}
* update armffa command with the new driver interfaces

v2  [2]:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1  [1]:

* introduce FF-A bus driver with device tree support
* introduce armffa command
* introduce FF-A Sandbox driver
* add FF-A Sandbox test cases
* introduce FF-A MM communication

Cheers,
Abdellatif

List of previous patches:

[1]: https://lore.kernel.org/all/20220329151659.16894-1-abdellatif.elkhlifi@arm.com/
[2]: https://lore.kernel.org/all/20220415122803.16666-1-abdellatif.elkhlifi@arm.com/
[3]: https://lore.kernel.org/all/20220801172053.20163-1-abdellatif.elkhlifi@arm.com/
[4]: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/
[5]: https://lore.kernel.org/all/20220926140827.15125-1-abdellatif.elkhlifi@arm.com/
[6]: https://lore.kernel.org/all/20221013103857.614-1-abdellatif.elkhlifi@arm.com/
[7]: https://lore.kernel.org/all/20221107192055.21669-1-abdellatif.elkhlifi@arm.com/
[8]: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/
[9]: https://lore.kernel.org/all/20230310141016.137986-1-abdellatif.elkhlifi@arm.com/
[10]: https://lore.kernel.org/all/20230328161157.219375-1-abdellatif.elkhlifi@arm.com/
[11]: https://lore.kernel.org/all/20230412094245.44674-1-abdellatif.elkhlifi@arm.com/
[12]: https://lore.kernel.org/all/20230512121044.111574-1-abdellatif.elkhlifi@arm.com/
[13]: https://lore.kernel.org/all/20230616152817.319869-1-abdellatif.elkhlifi@arm.com/
[14]: https://lore.kernel.org/all/20230707144410.228472-1-abdellatif.elkhlifi@arm.com/
[15]: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/
[16]: https://lore.kernel.org/all/20230726094503.100497-1-abdellatif.elkhlifi@arm.com/
[17]: https://lore.kernel.org/all/20230727160712.81477-1-abdellatif.elkhlifi@arm.com/
[18]: https://lore.kernel.org/all/20230803160350.477781-1-abdellatif.elkhlifi@arm.com/

More details:

[A]: https://developer.arm.com/documentation/den0077/latest/
[B]: doc/arch/arm64.ffa.rst
[C]: doc/usage/cmd/armffa.rst
[D]: example of boot logs when enabling FF-A

```
   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64

   DRAM:  2 GiB
   Arm FF-A framework discovery
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   ...
   FF-A driver 1.0
   FF-A framework 1.0
   FF-A versions are compatible
   EFI: MM partition ID 0x8003
   ...
   EFI stub: Booting Linux Kernel...
   ...
   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
   Machine model: ARM Corstone1000 FPGA MPS3 board
```

Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Achin Gupta <achin.gupta@arm.com>
Cc: Drew Reed <Drew.Reed@arm.com>
Cc: Xueliang Zhong <Xueliang.Zhong@arm.com>

Abdellatif El Khlifi (9):
  arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  lib: uuid: introduce uuid_str_to_le_bin function
  lib: uuid: introduce testcase for uuid_str_to_le_bin
  arm_ffa: introduce Arm FF-A support
  arm_ffa: introduce sandbox FF-A support
  arm_ffa: introduce sandbox test cases for UCLASS_FFA
  arm_ffa: introduce armffa command
  arm_ffa: efi: introduce FF-A MM communication
  arm_ffa: efi: corstone1000: enable MM communication

 MAINTAINERS                                   |   18 +
 arch/arm/cpu/armv8/smccc-call.S               |   57 +-
 arch/arm/lib/asm-offsets.c                    |   16 +
 arch/sandbox/dts/sandbox.dtsi                 |    9 +
 arch/sandbox/dts/test.dts                     |    8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |   72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        |  121 ++
 cmd/Kconfig                                   |   10 +
 cmd/Makefile                                  |    1 +
 cmd/armffa.c                                  |  202 ++++
 configs/corstone1000_defconfig                |   13 +-
 configs/sandbox64_defconfig                   |    1 +
 configs/sandbox_defconfig                     |    1 +
 doc/arch/arm64.ffa.rst                        |  261 ++++
 doc/arch/index.rst                            |    1 +
 doc/arch/sandbox/sandbox.rst                  |    1 +
 doc/usage/cmd/armffa.rst                      |   94 ++
 doc/usage/index.rst                           |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   42 +
 drivers/firmware/arm-ffa/Makefile             |   16 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 drivers/firmware/arm-ffa/ffa-emul-uclass.c    |  720 +++++++++++
 drivers/firmware/arm-ffa/sandbox_ffa.c        |  110 ++
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/dm/uclass-id.h                        |    7 +
 include/linux/arm-smccc.h                     |   45 +
 include/mm_communication.h                    |   17 +
 include/uuid.h                                |   15 +
 lib/efi_loader/Kconfig                        |   39 +-
 lib/efi_loader/efi_variable_tee.c             |  270 ++++-
 lib/uuid.c                                    |   48 +
 test/cmd/Makefile                             |    2 +
 test/cmd/armffa.c                             |   33 +
 test/dm/Makefile                              |    3 +-
 test/dm/ffa.c                                 |  261 ++++
 test/lib/Makefile                             |    1 +
 test/lib/uuid.c                               |   41 +
 41 files changed, 4174 insertions(+), 13 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 cmd/armffa.c
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 doc/usage/cmd/armffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h
 create mode 100644 test/cmd/armffa.c
 create mode 100644 test/dm/ffa.c
 create mode 100644 test/lib/uuid.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH v19 1/9] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers
  2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-08-04 13:33                                                                                                                                                                                     ` Abdellatif El Khlifi
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 2/9] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
                                                                                                                                                                                                       ` (9 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-04 13:33 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, sjg, u-boot

add support for x0-x17 registers used by the SMC calls

In SMCCC v1.2 [1] arguments are passed in registers x1-x17.
Results are returned in x0-x17.

This work is inspired from the following kernel commit:

arm64: smccc: Add support for SMCCCv1.2 extended input/output registers

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token=

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>

---

Changelog:
===============

v9:

* update the copyright string

v7:

* improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS

v4:

* rename the commit title and improve description
  new commit title: the current

v3:

* port x0-x17 registers support from linux kernel as defined by SMCCCv1.2
  commit title:
      arm64: smccc: add Xn registers support used by SMC calls

arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++-
 arch/arm/lib/asm-offsets.c      | 16 +++++++++
 include/linux/arm-smccc.h       | 45 ++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index dc92b28777..93f66d3366 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,7 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
- */
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+*/
 #include <linux/linkage.h>
 #include <linux/arm-smccc.h>
 #include <generated/asm-offsets.h>
@@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc)
 ENTRY(__arm_smccc_hvc)
 	SMCCC	hvc
 ENDPROC(__arm_smccc_hvc)
+
+#ifdef CONFIG_ARM64
+
+	.macro SMCCC_1_2 instr
+	/* Save `res` and free a GPR that won't be clobbered */
+	stp     x1, x19, [sp, #-16]!
+
+	/* Ensure `args` won't be clobbered while loading regs in next step */
+	mov	x19, x0
+
+	/* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */
+	ldp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	ldp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	ldp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	ldp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	ldp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	ldp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	ldp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	ldp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	ldp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	\instr #0
+
+	/* Load the `res` from the stack */
+	ldr	x19, [sp]
+
+	/* Store the registers x0 - x17 into the result structure */
+	stp	x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS]
+	stp	x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS]
+	stp	x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS]
+	stp	x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS]
+	stp	x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS]
+	stp	x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS]
+	stp	x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS]
+	stp	x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS]
+	stp	x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS]
+
+	/* Restore original x19 */
+	ldp     xzr, x19, [sp], #16
+	ret
+	.endm
+
+/*
+ * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+ *			  struct arm_smccc_1_2_regs *res);
+ */
+ENTRY(arm_smccc_1_2_smc)
+	SMCCC_1_2 smc
+ENDPROC(arm_smccc_1_2_smc)
+
+#endif
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index 6de0ce9152..181a8ac4c2 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -9,6 +9,11 @@
  * generate asm statements containing #defines,
  * compile this file to assembler, and then extract the
  * #defines from the assembly-language output.
+ *
+ * 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>
@@ -90,6 +95,17 @@ int main(void)
 	DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
 	DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
 	DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#ifdef CONFIG_ARM64
+	DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS,	offsetof(struct arm_smccc_1_2_regs, a0));
+	DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS,	offsetof(struct arm_smccc_1_2_regs, a2));
+	DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS,	offsetof(struct arm_smccc_1_2_regs, a4));
+	DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS,	offsetof(struct arm_smccc_1_2_regs, a6));
+	DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS,	offsetof(struct arm_smccc_1_2_regs, a8));
+	DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS,	offsetof(struct arm_smccc_1_2_regs, a10));
+	DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS,	offsetof(struct arm_smccc_1_2_regs, a12));
+	DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS,	offsetof(struct arm_smccc_1_2_regs, a14));
+	DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS,	offsetof(struct arm_smccc_1_2_regs, a16));
+#endif
 #endif
 
 	return 0;
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index e1d09884a1..f44e9e8f93 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,6 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015, Linaro Limited
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __LINUX_ARM_SMCCC_H
 #define __LINUX_ARM_SMCCC_H
@@ -70,6 +74,47 @@ struct arm_smccc_res {
 	unsigned long a3;
 };
 
+#ifdef CONFIG_ARM64
+/**
+ * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct arm_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;
+};
+
+/**
+ * arm_smccc_1_2_smc() - make SMC calls
+ * @args: arguments passed via struct arm_smccc_1_2_regs
+ * @res: result values via struct arm_smccc_1_2_regs
+ *
+ * This function is used to make SMC calls following SMC Calling Convention
+ * v1.2 or above. The content of the supplied param are copied from the
+ * structure to registers prior to the SMC instruction. The return values
+ * are updated with the content from registers on return from the SMC
+ * instruction.
+ */
+asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
+				  struct arm_smccc_1_2_regs *res);
+#endif
+
 /**
  * struct arm_smccc_quirk - Contains quirk information
  * @id: quirk identification
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v19 2/9] lib: uuid: introduce uuid_str_to_le_bin function
  2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 1/9] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
@ 2023-08-04 13:33                                                                                                                                                                                     ` Abdellatif El Khlifi
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 3/9] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
                                                                                                                                                                                                       ` (8 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-04 13:33 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, sjg, u-boot

convert UUID string to little endian binary data

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v9:

* add a full function prototype description in uuid.h

v8:

* use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms

v7:

* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin()
  by using same APIs

v4:

* rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in
  a standalone commit (the current)

v3:

* introduce ffa_uuid_str_to_bin (provided by
  arm_ffa: introduce Arm FF-A low-level driver)

include/uuid.h | 15 +++++++++++++++
 lib/uuid.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/uuid.h b/include/uuid.h
index 4a4883d3b5..89b93e642b 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -2,6 +2,10 @@
 /*
  * Copyright (C) 2014 Samsung Electronics
  * Przemyslaw Marczak <p.marczak@samsung.com>
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 #ifndef __UUID_H__
 #define __UUID_H__
@@ -44,4 +48,15 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin);
 const char *uuid_guid_get_str(const unsigned char *guid_bin);
 void gen_rand_uuid(unsigned char *uuid_bin);
 void gen_rand_uuid_str(char *uuid_str, int str_format);
+
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ * Return:
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin);
+
 #endif
diff --git a/lib/uuid.c b/lib/uuid.c
index 96e1af3c8b..45f325d964 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -1,6 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2011 Calxeda, Inc.
+ * 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>
@@ -354,6 +358,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin,
 	return 0;
 }
 
+/**
+ * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
+ * @uuid_str:	pointer to UUID string
+ * @uuid_bin:	pointer to allocated array for little endian output [16B]
+ *
+ * UUID string is 36 characters (36 bytes):
+ *
+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *
+ * where x is a hexadecimal character. Fields are separated by '-'s.
+ * When converting to a little endian binary UUID, the string fields are reversed.
+ *
+ * Return:
+ *
+ *    uuid_bin filled with little endian UUID data
+ *    On success 0 is returned. Otherwise, failure code.
+ */
+int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
+{
+	u16 tmp16;
+	u32 tmp32;
+	u64 tmp64;
+
+	if (!uuid_str_valid(uuid_str) || !uuid_bin)
+		return -EINVAL;
+
+	tmp32 = cpu_to_le32(hextoul(uuid_str, NULL));
+	memcpy(uuid_bin, &tmp32, 4);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL));
+	memcpy(uuid_bin + 4, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL));
+	memcpy(uuid_bin + 6, &tmp16, 2);
+
+	tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
+	memcpy(uuid_bin + 8, &tmp16, 2);
+
+	tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16));
+	memcpy(uuid_bin + 10, &tmp64, 6);
+
+	return 0;
+}
+
 /*
  * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID.
  *
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v19 3/9] lib: uuid: introduce testcase for uuid_str_to_le_bin
  2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 1/9] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 2/9] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
@ 2023-08-04 13:33                                                                                                                                                                                     ` Abdellatif El Khlifi
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 4/9] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                       ` (7 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-04 13:33 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, sjg, u-boot

provide a test case

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>

---

Changelog:
===============

v16:

* MAINTAINERS: place the UUID part in an alphabetical order

v11:

* use ut_asserteq_mem()

MAINTAINERS       |  5 +++++
 test/lib/Makefile |  1 +
 test/lib/uuid.c   | 41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)
 create mode 100644 test/lib/uuid.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d724b64673..4324965d26 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1555,6 +1555,11 @@ T:	git https://source.denx.de/u-boot/custodians/u-boot-usb.git topic-xhci
 F:	drivers/usb/host/xhci*
 F:	include/usb/xhci.h
 
+UUID testing
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+F:	test/lib/uuid.c
+
 VIDEO
 M:	Anatolij Gustschin <agust@denx.de>
 S:	Maintained
diff --git a/test/lib/Makefile b/test/lib/Makefile
index e0bd9e04e8..e75a263e6a 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_AES) += test_aes.o
 obj-$(CONFIG_GETOPT) += getopt.o
 obj-$(CONFIG_CRC8) += test_crc8.o
 obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o
+obj-$(CONFIG_LIB_UUID) += uuid.o
 else
 obj-$(CONFIG_SANDBOX) += kconfig_spl.o
 endif
diff --git a/test/lib/uuid.c b/test/lib/uuid.c
new file mode 100644
index 0000000000..e24331a136
--- /dev/null
+++ b/test/lib/uuid.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <uuid.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* test UUID */
+#define TEST_SVC_UUID	"ed32d533-4209-99e6-2d72-cdd998a79cc0"
+
+#define UUID_SIZE 16
+
+/* The UUID binary data (little-endian format) */
+static const u8 ref_uuid_bin[UUID_SIZE] = {
+	0x33, 0xd5, 0x32, 0xed,
+	0x09, 0x42, 0xe6, 0x99,
+	0x72, 0x2d, 0xc0, 0x9c,
+	0xa7, 0x98, 0xd9, 0xcd
+};
+
+static int lib_test_uuid_to_le(struct unit_test_state *uts)
+{
+	const char *uuid_str = TEST_SVC_UUID;
+	u8 ret_uuid_bin[UUID_SIZE] = {0};
+
+	ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin));
+	ut_asserteq_mem(ref_uuid_bin, ret_uuid_bin, UUID_SIZE);
+
+	return 0;
+}
+
+LIB_TEST(lib_test_uuid_to_le, 0);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v19 4/9] arm_ffa: introduce Arm FF-A support
  2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                       ` (2 preceding siblings ...)
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 3/9] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
@ 2023-08-04 13:33                                                                                                                                                                                     ` Abdellatif El Khlifi
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 5/9] arm_ffa: introduce sandbox " Abdellatif El Khlifi
                                                                                                                                                                                                       ` (6 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-04 13:33 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, sjg, u-boot, Heinrich Schuchardt

Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- ffa_partition_info_get
- ffa_sync_send_receive
- ffa_rxtx_unmap

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 please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v13:

* doc minor change: specify in the readme that the user
   should call ffa_rxtx_unmap() driver operation to unmap
   the RX/TX buffers on demand.

v12:

* remove dscvry_info
* replace dscvry_info.invoke_ffa_fn() with a weak invoke_ffa_fn
   (user drivers can override it)
* improve FFA_PARTITION_INFO_GET implementation
   (clients no longer need to calloc a buffer)
* address nits

v11:

* move ffa_try_discovery() from the uclass to the Arm FF-A driver
* rename ffa_try_discovery() to arm_ffa_discover()
* pass dev as an argument of arm_ffa_discover()
* add arm_ prefix to the Arm FF-A driver functions
* add emul field in struct ffa_discovery_info
* address nits

v10:

* provide the driver operations through the Uclass
* move the generic FF-A methods to the Uclass
* keep Arm specific methods in the Arm driver (arm-ffa.c)
* rename core.c to arm-ffa.c
* address nits

v9:

* integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding

v8:

* make ffa_get_partitions_info() second argument to be an SP count in both
  modes
* update ffa_bus_prvdata_get() to return a pointer rather than a pointer
  address
* remove packing from ffa_partition_info and ffa_send_direct_data structures
* pass the FF-A bus device to the bus operations

v7:

* add support for 32-bit direct messaging
* rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin()
* improve the declaration of error handling mapping
* stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported

v6:

* drop use of EFI runtime support (We decided with Linaro to add this later)
* drop discovery from initcalls (discovery will be on demand by FF-A users)
* set the alignment of the RX/TX buffers to the larger translation granule size
* move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit
* update the documentation and move it to doc/arch/arm64.ffa.rst

v4:

* add doc/README.ffa.drv
* moving the FF-A driver work to drivers/firmware/arm-ffa
* use less #ifdefs in lib/efi_loader/efi_boottime.c and replace
  #if defined by #if CONFIG_IS_ENABLED
* improving error handling by mapping the FF-A errors to standard errors
  and logs
* replacing panics with an error log and returning an error code
* improving features discovery in FFA_FEATURES by introducing
  rxtx_min_pages private data field
* add ffa_remove and ffa_unbind functions
* improve how the driver behaves when bus discovery is done more than
  once

v3:

* align the interfaces of the U-Boot FF-A driver with those in the linux
  FF-A driver
* remove the FF-A helper layer
* make the U-Boot FF-A driver independent from EFI
* provide an optional config that enables copying the driver data to EFI
  runtime section at ExitBootServices service
* use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP}

v2:

* make FF-A bus discoverable using device_{bind, probe} APIs
* remove device tree support

v1:

* introduce FF-A bus driver with device tree support

MAINTAINERS                                   |    8 +
 doc/arch/arm64.ffa.rst                        |  236 ++++
 doc/arch/index.rst                            |    1 +
 drivers/Makefile                              |    1 +
 drivers/firmware/Kconfig                      |    1 +
 drivers/firmware/arm-ffa/Kconfig              |   36 +
 drivers/firmware/arm-ffa/Makefile             |    8 +
 drivers/firmware/arm-ffa/arm-ffa-uclass.c     | 1065 +++++++++++++++++
 drivers/firmware/arm-ffa/arm-ffa.c            |  104 ++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |   14 +
 include/arm_ffa.h                             |  213 ++++
 include/arm_ffa_priv.h                        |  246 ++++
 include/dm/uclass-id.h                        |    6 +
 13 files changed, 1939 insertions(+)
 create mode 100644 doc/arch/arm64.ffa.rst
 create mode 100644 drivers/firmware/arm-ffa/Kconfig
 create mode 100644 drivers/firmware/arm-ffa/Makefile
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c
 create mode 100644 drivers/firmware/arm-ffa/arm-ffa.c
 create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
 create mode 100644 include/arm_ffa.h
 create mode 100644 include/arm_ffa_priv.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 4324965d26..4fd5768de0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,6 +266,14 @@ F:	drivers/net/cortina_ni.h
 F:	drivers/net/phy/ca_phy.c
 F:	configs/cortina_presidio-asic-pnand_defconfig
 
+ARM FF-A
+M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+S:	Maintained
+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>
 M:	Fabio Estevam <festevam@gmail.com>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
new file mode 100644
index 0000000000..df18948774
--- /dev/null
+++ b/doc/arch/arm64.ffa.rst
@@ -0,0 +1,236 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Arm FF-A Support
+================
+
+Summary
+-------
+
+FF-A stands for Firmware Framework for Arm A-profile processors.
+
+FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
+communicate with each other. A partition could be a VM in the Normal or Secure world, an
+application in S-EL0, or a Trusted OS in S-EL1.
+
+The U-Boot FF-A support (the bus) implements the interfaces to communicate
+with partitions in the Secure world aka Secure partitions (SPs).
+
+The FF-A support specifically focuses on communicating with SPs that
+isolate portions of EFI runtime services that must run in a protected
+environment which is inaccessible by the Host OS or Hypervisor.
+Examples of such services are set/get variables.
+
+The FF-A support uses the SMC ABIs defined by the FF-A specification to:
+
+- Discover the presence of SPs of interest
+- Access an SP's service through communication protocols
+  e.g. EFI MM communication protocol
+
+At this stage of development only EFI boot-time services are supported.
+Runtime support will be added in future developments.
+
+The U-Boot FF-A support provides the following parts:
+
+- A Uclass driver providing generic FF-A methods.
+- An Arm FF-A device driver providing Arm-specific methods and reusing the Uclass methods.
+
+FF-A and SMC specifications
+-------------------------------------------
+
+The current implementation of the U-Boot FF-A support relies on
+`FF-A v1.0 specification`_ and uses SMC32 calling convention which
+means using the first 32-bit data of the Xn registers.
+
+At this stage we only need the FF-A v1.0 features.
+
+The FF-A support has been tested with OP-TEE which supports SMC32 calling
+convention.
+
+Hypervisors are supported if they are configured to trap SMC calls.
+
+The FF-A support uses 64-bit registers as per `SMC Calling Convention v1.2 specification`_.
+
+Supported hardware
+--------------------------------
+
+Aarch64 plaforms
+
+Configuration
+----------------------
+
+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.
+
+FF-A ABIs under the hood
+---------------------------------------
+
+Invoking an FF-A ABI involves providing to the secure world/hypervisor the
+expected arguments from the ABI.
+
+On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers.
+Then, an SMC instruction is executed.
+
+At the secure side level or hypervisor the ABI is handled at a higher exception
+level and the arguments are read and processed.
+
+The response is put back through x0 to x7 registers and control is given back
+to the U-Boot Arm FF-A driver (non-secure world).
+
+The driver reads the response and processes it accordingly.
+
+This methodology applies to all the FF-A ABIs.
+
+FF-A bus discovery on Arm 64-bit platforms
+---------------------------------------------
+
+When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
+an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
+This discovery mechanism is performed by the PSCI driver.
+
+The PSCI driver comes with a PSCI device tree node which is the root node for all
+architecture features including FF-A bus.
+
+::
+
+   => dm tree
+
+    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.
+
+In case of FF-A, the callback is arm_ffa_is_supported() which tries to discover the
+FF-A framework by querying the FF-A framework version from secure world using
+FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
+mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver
+with the device using device_bind_driver().
+
+At this stage the FF-A bus is registered with the DM and can be interacted with using
+the DM APIs.
+
+Clients are able to probe then use the FF-A bus by calling uclass_first_device().
+
+When calling uclass_first_device(), the FF-A driver is probed and ends up calling
+ffa_do_probe() provided by the Uclass which does the following:
+
+    - saving the FF-A framework version in uc_priv
+    - querying from secure world the u-boot endpoint ID
+    - querying from secure world the supported features of FFA_RXTX_MAP
+    - mapping the RX/TX buffers
+    - querying from secure world all the partitions information
+
+When one of the above actions fails, probing fails and the driver stays not active
+and can be probed again if needed.
+
+Requirements for clients
+-------------------------------------
+
+When using the FF-A bus with EFI, clients must query the SPs they are looking for
+during EFI boot-time mode using the service UUID.
+
+The RX/TX buffers are only available at EFI boot-time. Querying partitions is
+done at boot time and data is cached for future use.
+
+RX/TX buffers should be unmapped before EFI runtime mode starts.
+The driver provides a bus operation for that called ffa_rxtx_unmap().
+
+The user should call ffa_rxtx_unmap() to unmap the RX/TX buffers when required
+(e.g: at efi_exit_boot_services()).
+
+The Linux kernel allocates its own RX/TX buffers. To be able to register these kernel buffers
+with secure world, the U-Boot's RX/TX buffers should be unmapped before EFI runtime starts.
+
+When invoking FF-A direct messaging, clients should specify which ABI protocol
+they want to use (32-bit vs 64-bit). Selecting the protocol means using
+the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
+The calling convention between U-Boot and the secure world stays the same: SMC32.
+
+Requirements for user drivers
+-------------------------------------
+
+Users who want to implement their custom FF-A device driver while reusing the FF-A Uclass can do so
+by implementing their own invoke_ffa_fn() in the user driver.
+
+The bus driver layer
+------------------------------
+
+FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c
+
+The following features are provided:
+
+- Support for the 32-bit version of the following ABIs:
+
+    - FFA_VERSION
+    - FFA_ID_GET
+    - FFA_FEATURES
+    - FFA_PARTITION_INFO_GET
+    - FFA_RXTX_UNMAP
+    - FFA_RX_RELEASE
+    - FFA_RUN
+    - FFA_ERROR
+    - FFA_SUCCESS
+    - FFA_INTERRUPT
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Support for the 64-bit version of the following ABIs:
+
+    - FFA_RXTX_MAP
+    - FFA_MSG_SEND_DIRECT_REQ
+    - FFA_MSG_SEND_DIRECT_RESP
+
+- Processing the received data from the secure world/hypervisor and caching it
+
+- Hiding from upper layers the FF-A protocol and registers details. Upper
+  layers focus on exchanged data, FF-A support takes care of how to transport
+  that to the secure world/hypervisor using FF-A
+
+- FF-A support provides driver operations to be used by upper layers:
+
+    - ffa_partition_info_get
+    - ffa_sync_send_receive
+    - ffa_rxtx_unmap
+
+- FF-A bus discovery makes sure FF-A framework is responsive and compatible
+  with the driver
+
+- FF-A bus can be compiled and used without EFI
+
+Example of boot logs with FF-A enabled
+--------------------------------------
+
+For example, when using FF-A with Corstone-1000 the logs are as follows:
+
+::
+
+   U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64
+
+   DRAM:  2 GiB
+   Arm FF-A framework discovery
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   ...
+   FF-A driver 1.0
+   FF-A framework 1.0
+   FF-A versions are compatible
+   EFI: MM partition ID 0x8003
+   ...
+   EFI stub: Booting Linux Kernel...
+   ...
+   Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
+   Machine model: ARM Corstone1000 FPGA MPS3 board
+
+Contributors
+------------
+   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+
+.. _`FF-A v1.0 specification`: https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e
+.. _`SMC Calling Convention v1.2 specification`: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6
diff --git a/doc/arch/index.rst b/doc/arch/index.rst
index b8da4b8c8e..2f916f4026 100644
--- a/doc/arch/index.rst
+++ b/doc/arch/index.rst
@@ -8,6 +8,7 @@ Architecture-specific doc
 
    arc
    arm64
+   arm64.ffa
    m68k
    mips
    nios2
diff --git a/drivers/Makefile b/drivers/Makefile
index 78dcf62f76..5044f45253 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -115,6 +115,7 @@ obj-y += iommu/
 obj-y += smem/
 obj-y += thermal/
 obj-$(CONFIG_TEE) += tee/
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
 obj-y += axi/
 obj-y += ufs/
 obj-$(CONFIG_W1) += w1/
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index eae1c8ddc9..8789b1ea14 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
 	  the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
 	  services if any and reported as supported by the SMCCC firmware.
 
+source "drivers/firmware/arm-ffa/Kconfig"
 source "drivers/firmware/scmi/Kconfig"
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
new file mode 100644
index 0000000000..9200c8028b
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARM_FFA_TRANSPORT
+	bool "Enable Arm Firmware Framework for Armv8-A driver"
+	depends on DM && ARM64
+	select ARM_SMCCC
+	select ARM_SMCCC_FEATURES
+	select LIB_UUID
+	select DEVRES
+	help
+	  The Firmware Framework for Arm A-profile processors (FF-A)
+	  describes interfaces (ABIs) that standardize communication
+	  between the Secure World and Normal World leveraging TrustZone
+	  technology.
+
+	  The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32
+	  calling convention.
+
+	  FF-A specification:
+
+	  https://developer.arm.com/documentation/den0077/a/?lang=en
+
+	  In U-Boot FF-A design, FF-A is considered as a discoverable bus.
+	  FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
+	  by the PSCI driver.
+	  The Secure World is considered as one entity to communicate with
+	  using the FF-A bus.
+	  FF-A communication is handled by one device and one instance (the bus).
+	  The FF-A support on U-Boot  takes care of all the interactions between Normal
+	  world and Secure World.
+
+	  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
+
diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
new file mode 100644
index 0000000000..11b1766285
--- /dev/null
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -0,0 +1,8 @@
+# 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>
+
+obj-y += arm-ffa-uclass.o arm-ffa.o
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
new file mode 100644
index 0000000000..ffa9d81fa7
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -0,0 +1,1065 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <string.h>
+#include <uuid.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/devres.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Error mapping declarations */
+
+int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {
+	[NOT_SUPPORTED] = -EOPNOTSUPP,
+	[INVALID_PARAMETERS] = -EINVAL,
+	[NO_MEMORY] = -ENOMEM,
+	[BUSY] = -EBUSY,
+	[INTERRUPTED] = -EINTR,
+	[DENIED] = -EACCES,
+	[RETRY] = -EAGAIN,
+	[ABORTED] = -ECANCELED,
+};
+
+static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {
+	[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: A Firmware Framework implementation does not exist",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Unrecognized UUID",
+			[NO_MEMORY] =
+			"NO_MEMORY: Results cannot fit in RX buffer of the caller",
+			[BUSY] =
+			"BUSY: RX buffer of the caller is not free",
+			[DENIED] =
+			"DENIED: Callee is not in a state to handle this request",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: No buffer pair registered on behalf of the caller",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance",
+			[DENIED] =
+			"DENIED: Caller did not have ownership of the RX buffer",
+		},
+	},
+	[FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = {
+		{
+			[NOT_SUPPORTED] =
+			"NOT_SUPPORTED: This function is not implemented at this FF-A instance",
+			[INVALID_PARAMETERS] =
+			"INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded",
+			[NO_MEMORY] =
+			"NO_MEMORY: Not enough memory",
+			[DENIED] =
+			"DENIED: Buffer pair already registered",
+		},
+	},
+};
+
+/**
+ * ffa_to_std_errno() - convert FF-A error code to standard error code
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the given FF-A error code as specified
+ * by the spec to a u-boot standard error code.
+ *
+ * Return:
+ *
+ * The standard error code on success. . Otherwise, failure
+ */
+static int ffa_to_std_errno(int ffa_errno)
+{
+	int err_idx = -ffa_errno;
+
+	/* Map the FF-A error code to the standard u-boot error code */
+	if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)
+		return ffa_to_std_errmap[err_idx];
+	return -EINVAL;
+}
+
+/**
+ * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI
+ * @ffa_id:	FF-A ABI ID
+ * @ffa_errno:	Error code returned by the FF-A ABI
+ *
+ * Map the FF-A error code to the error log relevant to the
+ * selected FF-A ABI. Then the error log is printed.
+ *
+ * Return:
+ *
+ * 0 on success. . Otherwise, failure
+ */
+static int ffa_print_error_log(u32 ffa_id, int ffa_errno)
+{
+	int err_idx = -ffa_errno, abi_idx = 0;
+
+	/* Map the FF-A error code to the corresponding error log */
+
+	if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR)
+		return -EINVAL;
+
+	if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID)
+		return -EINVAL;
+
+	abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id);
+	if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT)
+		return -EINVAL;
+
+	if (!err_msg_map[abi_idx].err_str[err_idx])
+		return -EINVAL;
+
+	log_err("%s\n", err_msg_map[abi_idx].err_str[err_idx]);
+
+	return 0;
+}
+
+/* FF-A ABIs implementation (U-Boot side) */
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void __weak invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+}
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev)
+{
+	u16 major, minor;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0,
+			}, &res);
+
+	ffa_errno = res.a0;
+	if (ffa_errno < 0) {
+		ffa_print_error_log(FFA_VERSION, ffa_errno);
+		return ffa_to_std_errno(ffa_errno);
+	}
+
+	major = GET_FFA_MAJOR_VERSION(res.a0);
+	minor = GET_FFA_MINOR_VERSION(res.a0);
+
+	log_info("FF-A driver %d.%d\nFF-A framework %d.%d\n",
+		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) {
+		log_info("FF-A versions are compatible\n");
+
+		if (dev) {
+			uc_priv = dev_get_uclass_priv(dev);
+			if (uc_priv)
+				uc_priv->fwk_version = res.a0;
+		}
+
+		return 0;
+	}
+
+	log_err("versions are incompatible\nExpected: %d.%d , Found: %d.%d\n",
+		FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
+
+	return -EPROTONOSUPPORT;
+}
+
+/**
+ * ffa_get_endpoint_id() - FFA_ID_GET handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_ID_GET FF-A function
+ * to get from the secure world u-boot endpoint ID
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_endpoint_id(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_ID_GET),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		uc_priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2);
+		log_debug("FF-A endpoint ID is %u\n", uc_priv->id);
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+
+	ffa_print_error_log(FFA_ID_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_set_rxtx_buffers_pages_cnt() - set the minimum number of pages in each of the RX/TX buffers
+ * @dev: The FF-A bus device
+ * @prop_field: properties field obtained from FFA_FEATURES ABI
+ *
+ * Set the minimum number of pages in each of the RX/TX buffers in uc_priv
+ *
+ * Return:
+ *
+ * rxtx_min_pages field contains the returned number of pages
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	switch (prop_field) {
+	case RXTX_4K:
+		uc_priv->pair.rxtx_min_pages = 1;
+		break;
+	case RXTX_16K:
+		uc_priv->pair.rxtx_min_pages = 4;
+		break;
+	case RXTX_64K:
+		uc_priv->pair.rxtx_min_pages = 16;
+		break;
+	default:
+		log_err("RX/TX buffer size not supported\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_get_rxtx_map_features_hdlr() - FFA_FEATURES handler function with FFA_RXTX_MAP argument
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_FEATURES FF-A function to retrieve the FFA_RXTX_MAP features
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_rxtx_map_features_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_FEATURES),
+			.a1 = FFA_SMC_64(FFA_RXTX_MAP),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2);
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_FEATURES, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_free_rxtx_buffers() - free the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Free the RX/TX buffers
+ */
+static void ffa_free_rxtx_buffers(struct udevice *dev)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Freeing FF-A RX/TX buffers\n");
+
+	if (uc_priv->pair.rxbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+	}
+
+	if (uc_priv->pair.txbuf) {
+		free(uc_priv->pair.txbuf);
+		uc_priv->pair.txbuf = NULL;
+	}
+}
+
+/**
+ * ffa_alloc_rxtx_buffers() - allocate the RX/TX buffers
+ * @dev: The FF-A bus device
+ *
+ * Used by ffa_map_rxtx_buffers to allocate
+ * the RX/TX buffers before mapping them. The allocated memory is physically
+ * contiguous since memalign ends up calling malloc which allocates
+ * contiguous memory in u-boot.
+ * The size of the memory allocated is the minimum allowed.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_alloc_rxtx_buffers(struct udevice *dev)
+{
+	u64 bytes;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	log_debug("Using %lu 4KB page(s) for FF-A RX/TX buffers size\n",
+		  uc_priv->pair.rxtx_min_pages);
+
+	bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+	/*
+	 * The alignment of the RX and TX buffers must be equal
+	 * to the larger translation granule size
+	 * Assumption: Memory allocated with memalign is always physically contiguous
+	 */
+
+	uc_priv->pair.rxbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.rxbuf) {
+		log_err("failure to allocate RX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A RX buffer at virtual address %p\n", uc_priv->pair.rxbuf);
+
+	uc_priv->pair.txbuf = memalign(bytes, bytes);
+	if (!uc_priv->pair.txbuf) {
+		free(uc_priv->pair.rxbuf);
+		uc_priv->pair.rxbuf = NULL;
+		log_err("failure to allocate the TX buffer\n");
+		return -ENOBUFS;
+	}
+
+	log_debug("FF-A TX buffer at virtual address %p\n", uc_priv->pair.txbuf);
+
+	/* Make sure the buffers are cleared before use */
+	memset(uc_priv->pair.rxbuf, 0, bytes);
+	memset(uc_priv->pair.txbuf, 0, bytes);
+
+	return 0;
+}
+
+/**
+ * ffa_map_rxtx_buffers_hdlr() - FFA_RXTX_MAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_MAP FF-A function to map the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_map_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	int ret;
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	ret = ffa_alloc_rxtx_buffers(dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * we need to pass the physical addresses of the RX/TX buffers
+	 * in u-boot physical/virtual mapping is 1:1
+	 * no need to convert from virtual to physical
+	 */
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_64(FFA_RXTX_MAP),
+			.a1 = map_to_sysmem(uc_priv->pair.txbuf),
+			.a2 = map_to_sysmem(uc_priv->pair.rxbuf),
+			.a3 = uc_priv->pair.rxtx_min_pages,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		log_debug("FF-A RX/TX buffers mapped\n");
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_MAP, ffa_errno);
+
+	ffa_free_rxtx_buffers(dev);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_RXTX_UNMAP FF-A function to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	struct ffa_priv *uc_priv;
+
+	log_debug("unmapping FF-A RX/TX buffers\n");
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		ffa_free_rxtx_buffers(dev);
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_release_rx_buffer_hdlr() - FFA_RX_RELEASE handler function
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_RX_RELEASE FF-A function to release the ownership of the RX buffer
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_release_rx_buffer_hdlr(struct udevice *dev)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RX_RELEASE),
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS))
+		return 0;
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_RX_RELEASE, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_uuid_are_identical() - check whether two given UUIDs are identical
+ * @uuid1: first UUID
+ * @uuid2: second UUID
+ *
+ * Used by ffa_read_partitions_info to search for a UUID in the partitions descriptors table
+ *
+ * Return:
+ *
+ * 1 when UUIDs match. Otherwise, 0
+ */
+static bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1,
+				   const struct ffa_partition_uuid *uuid2)
+{
+	if (!uuid1 || !uuid2)
+		return 0;
+
+	return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid));
+}
+
+/**
+ * ffa_read_partitions_info() - read queried partition data
+ * @dev: The FF-A bus device
+ * @count: The number of partitions queried
+ * @part_uuid: Pointer to the partition(s) UUID
+ *
+ * Read the partitions information returned by the FFA_PARTITION_INFO_GET and saves it in uc_priv
+ *
+ * Return:
+ *
+ * uc_priv is updated with the partition(s) information
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_read_partitions_info(struct udevice *dev, u32 count,
+				    struct ffa_partition_uuid *part_uuid)
+{
+	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	if (!count) {
+		log_err("no partition detected\n");
+		return -ENODATA;
+	}
+
+	log_debug("Reading FF-A partitions data from the RX buffer\n");
+
+	if (!part_uuid) {
+		/* Querying information of all partitions */
+		u64 buf_bytes;
+		u64 data_bytes;
+		u32 desc_idx;
+		struct ffa_partition_info *parts_info;
+
+		data_bytes = count * sizeof(struct ffa_partition_desc);
+
+		buf_bytes = uc_priv->pair.rxtx_min_pages * SZ_4K;
+
+		if (data_bytes > buf_bytes) {
+			log_err("partitions data size exceeds the RX buffer size:\n");
+			log_err("    sizes in bytes: data %llu , RX buffer %llu\n",
+				data_bytes,
+				buf_bytes);
+
+			return -ENOMEM;
+		}
+
+		uc_priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO);
+		if (!uc_priv->partitions.descs) {
+			log_err("cannot  allocate partitions data buffer\n");
+			return -ENOMEM;
+		}
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
+			uc_priv->partitions.descs[desc_idx].info =
+				parts_info[desc_idx];
+
+			log_debug("FF-A partition ID %x : info cached\n",
+				  uc_priv->partitions.descs[desc_idx].info.id);
+		}
+
+		uc_priv->partitions.count = count;
+
+		log_debug("%d FF-A partition(s) found and cached\n", count);
+
+	} else {
+		u32 rx_desc_idx, cached_desc_idx;
+		struct ffa_partition_info *parts_info;
+		u8 desc_found;
+
+		parts_info = uc_priv->pair.rxbuf;
+
+		/*
+		 * Search for the SP IDs read from the RX buffer
+		 * in the already cached SPs.
+		 * Update the UUID when ID found.
+		 */
+		for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
+			desc_found = 0;
+
+			/* Search the current ID in the cached partitions */
+			for (cached_desc_idx = 0;
+			     cached_desc_idx < uc_priv->partitions.count;
+			     cached_desc_idx++) {
+				/* Save the UUID */
+				if (uc_priv->partitions.descs[cached_desc_idx].info.id ==
+				    parts_info[rx_desc_idx].id) {
+					uc_priv->partitions.descs[cached_desc_idx].sp_uuid =
+						*part_uuid;
+
+					desc_found = 1;
+					break;
+				}
+			}
+
+			if (!desc_found)
+				return -ENODATA;
+		}
+	}
+
+	return  0;
+}
+
+/**
+ * ffa_query_partitions_info() - invoke FFA_PARTITION_INFO_GET and save partitions data
+ * @dev: The FF-A bus device
+ * @part_uuid: Pointer to the partition(s) UUID
+ * @pcount: Pointer to the number of partitions variable filled when querying
+ *
+ * Execute the FFA_PARTITION_INFO_GET to query the partitions data.
+ * Then, call ffa_read_partitions_info to save the data in uc_priv.
+ *
+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
+ *
+ * Return:
+ *
+ * When part_uuid is NULL, all partitions data are retrieved from secure world
+ * When part_uuid is non NULL, data for partitions matching the given UUID are
+ * retrieved and the number of partitions is returned
+ * 0 is returned on success. Otherwise, failure
+ */
+static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid,
+				     u32 *pcount)
+{
+	struct ffa_partition_uuid query_uuid = {0};
+	ffa_value_t res = {0};
+	int ffa_errno;
+
+	/*
+	 * If a UUID is specified. Information for one or more
+	 * partitions in the system is queried. Otherwise, information
+	 * for all installed partitions is queried
+	 */
+
+	if (part_uuid) {
+		if (!pcount)
+			return -EINVAL;
+
+		query_uuid = *part_uuid;
+	} else if (pcount) {
+		return -EINVAL;
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET),
+			.a1 = query_uuid.a1,
+			.a2 = query_uuid.a2,
+			.a3 = query_uuid.a3,
+			.a4 = query_uuid.a4,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		int ret;
+
+		/*
+		 * res.a2 contains the count of partition information descriptors
+		 * populated in the RX buffer
+		 */
+		if (res.a2) {
+			ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid);
+			if (ret) {
+				log_err("failed reading SP(s) data , err (%d)\n", ret);
+				ffa_release_rx_buffer_hdlr(dev);
+				return -EINVAL;
+			}
+		}
+
+		/* Return the SP count (when querying using a UUID) */
+		if (pcount)
+			*pcount = (u32)res.a2;
+
+		/*
+		 * After calling FFA_PARTITION_INFO_GET the buffer ownership
+		 * is assigned to the consumer (u-boot). So, we need to give
+		 * the ownership back to the SPM or hypervisor
+		 */
+		ret = ffa_release_rx_buffer_hdlr(dev);
+
+		return ret;
+	}
+
+	ffa_errno = res.a2;
+	ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno);
+
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET FF-A function to query the partition information
+ * from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * If the partition(s) matching the UUID found, the partition(s) information and the
+ * number are returned.
+ * If no partition matching the UUID is found in the cached area, a new FFA_PARTITION_INFO_GET
+ * call is issued.
+ * If not done yet, the UUID is updated in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	u32 i;
+	struct ffa_partition_uuid part_uuid = {0};
+	struct ffa_priv *uc_priv;
+	struct ffa_partition_desc *rx_descs;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs) {
+		log_err("no partition installed\n");
+		return -EINVAL;
+	}
+
+	if (!uuid_str) {
+		log_err("no UUID provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_count) {
+		log_err("no count argument provided\n");
+		return -EINVAL;
+	}
+
+	if (!sp_descs) {
+		log_err("no info argument provided\n");
+		return -EINVAL;
+	}
+
+	if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) {
+		log_err("invalid UUID\n");
+		return -EINVAL;
+	}
+
+	log_debug("Searching FF-A partitions using the provided UUID\n");
+
+	*sp_count = 0;
+	*sp_descs = uc_priv->pair.rxbuf;
+	rx_descs = *sp_descs;
+
+	/* Search in the cached partitions */
+	for (i = 0; i < uc_priv->partitions.count; i++)
+		if (ffa_uuid_are_identical(&uc_priv->partitions.descs[i].sp_uuid,
+					   &part_uuid)) {
+			log_debug("FF-A partition ID %x matches the provided UUID\n",
+				  uc_priv->partitions.descs[i].info.id);
+
+			(*sp_count)++;
+			*rx_descs++ = uc_priv->partitions.descs[i];
+			}
+
+	if (!(*sp_count)) {
+		int ret;
+
+		log_debug("No FF-A partition found. Querying framework ...\n");
+
+		ret = ffa_query_partitions_info(dev, &part_uuid, sp_count);
+
+		if (!ret) {
+			log_debug("Number of FF-A partition(s) matching the UUID: %d\n", *sp_count);
+
+			if (*sp_count)
+				ret = ffa_get_partitions_info_hdlr(dev, uuid_str, sp_count,
+								   sp_descs);
+			else
+				ret = -ENODATA;
+		}
+
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * ffa_cache_partitions_info() - Query and saves all secure partitions data
+ * @dev: The FF-A bus device
+ *
+ * Invoke FFA_PARTITION_INFO_GET FF-A function to query from secure world
+ * all partitions information.
+ *
+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
+ * All installed partitions information are returned. We cache them in uc_priv
+ * and we keep the UUID field empty (in FF-A 1.0 UUID is not provided by the partition descriptor)
+ *
+ * Called at the device probing level.
+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_cache_partitions_info(struct udevice *dev)
+{
+	return ffa_query_partitions_info(dev, NULL, NULL);
+}
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Implement FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	ffa_value_t res = {0};
+	int ffa_errno;
+	u64 req_mode, resp_mode;
+	struct ffa_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* No partition installed */
+	if (!uc_priv->partitions.count || !uc_priv->partitions.descs)
+		return -ENODEV;
+
+	if (is_smc64) {
+		req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+	} else {
+		req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);
+		resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);
+	}
+
+	invoke_ffa_fn((ffa_value_t){
+			.a0 = req_mode,
+			.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id) |
+				PREP_PART_ENDPOINT_ID(dst_part_id),
+			.a2 = 0,
+			.a3 = msg->data0,
+			.a4 = msg->data1,
+			.a5 = msg->data2,
+			.a6 = msg->data3,
+			.a7 = msg->data4,
+			}, &res);
+
+	while (res.a0 == FFA_SMC_32(FFA_INTERRUPT))
+		invoke_ffa_fn((ffa_value_t){
+			.a0 = FFA_SMC_32(FFA_RUN),
+			.a1 = res.a1,
+			}, &res);
+
+	if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {
+		/* Message sent with no response */
+		return 0;
+	}
+
+	if (res.a0 == resp_mode) {
+		/* Message sent with response extract the return data */
+		msg->data0 = res.a3;
+		msg->data1 = res.a4;
+		msg->data2 = res.a5;
+		msg->data3 = res.a6;
+		msg->data4 = res.a7;
+
+		return 0;
+	}
+
+	ffa_errno = res.a2;
+	return ffa_to_std_errno(ffa_errno);
+}
+
+/* FF-A driver operations (used by clients for communicating with FF-A)*/
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Driver operation for FFA_PARTITION_INFO_GET.
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->partition_info_get)
+		return -ENOSYS;
+
+	return ops->partition_info_get(dev, uuid_str, sp_count, sp_descs);
+}
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * @dev: The FF-A bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * Driver operation for FFA_MSG_SEND_DIRECT_{REQ,RESP}.
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->sync_send_receive)
+		return -ENOSYS;
+
+	return ops->sync_send_receive(dev, dst_part_id, msg, is_smc64);
+}
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * @dev: The FF-A bus device
+ *
+ * Driver operation for FFA_RXTX_UNMAP.
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_rxtx_unmap(struct udevice *dev)
+{
+	struct ffa_bus_ops *ops = ffa_get_ops(dev);
+
+	if (!ops->rxtx_unmap)
+		return -ENOSYS;
+
+	return ops->rxtx_unmap(dev);
+}
+
+/**
+ * ffa_do_probe() - probing FF-A framework
+ * @dev:	the FF-A bus device (arm_ffa)
+ *
+ * Probing is triggered on demand by clients searching for the uclass.
+ * At probe level the following actions are done:
+ *	- saving the FF-A framework version in uc_priv
+ *	- querying from secure world the u-boot endpoint ID
+ *	- querying from secure world the supported features of FFA_RXTX_MAP
+ *	- mapping the RX/TX buffers
+ *	- querying from secure world all the partitions information
+ *
+ * All data queried from secure world is saved in uc_priv.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_do_probe(struct udevice *dev)
+{
+	int ret;
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_endpoint_id(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_get_rxtx_map_features_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_map_rxtx_buffers_hdlr(dev);
+	if (ret)
+		return ret;
+
+	ret = ffa_cache_partitions_info(dev);
+	if (ret) {
+		ffa_unmap_rxtx_buffers_hdlr(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+UCLASS_DRIVER(ffa) = {
+	.name			= "ffa",
+	.id			= UCLASS_FFA,
+	.pre_probe		= ffa_do_probe,
+	.pre_remove		= ffa_unmap_rxtx_buffers_hdlr,
+	.per_device_auto	= sizeof(struct ffa_priv)
+};
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
new file mode 100644
index 0000000000..68df75bd9e
--- /dev/null
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -0,0 +1,104 @@
+// 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 <arm_ffa_priv.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <linux/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * 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 low level SMC assembly function
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
+{
+	arm_smccc_1_2_smc(&args, res);
+}
+
+/**
+ * arm_ffa_discover() - perform FF-A discovery
+ * @dev: The Arm FF-A bus device (arm_ffa)
+ * 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:
+ *
+ * true on success. Otherwise, false.
+ */
+static bool arm_ffa_discover(struct udevice *dev)
+{
+	int ret;
+
+	log_info("Arm FF-A framework discovery\n");
+
+	ret = ffa_get_version_hdlr(dev);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/**
+ * arm_ffa_is_supported() - FF-A bus discovery callback
+ * @invoke_fn: legacy SMC invoke function (not used)
+ *
+ * Perform FF-A discovery by calling arm_ffa_discover().
+ * Discovery is performed by querying the FF-A framework version from
+ * secure world using the FFA_VERSION ABI.
+ *
+ * The FF-A driver is registered as an SMCCC feature driver. So, features discovery
+ * callbacks are called by the PSCI driver (PSCI device is the SMCCC features
+ * root device).
+ *
+ * The FF-A driver supports the SMCCCv1.2 extended input/output registers.
+ * So, the legacy SMC invocation is not used.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static bool arm_ffa_is_supported(void (*invoke_fn)(ulong a0, ulong a1,
+						   ulong a2, ulong a3,
+						   ulong a4, ulong a5,
+						   ulong a6, ulong a7,
+						   struct arm_smccc_res *res))
+{
+	return arm_ffa_discover(NULL);
+}
+
+/* Arm FF-A driver operations */
+
+static const struct ffa_bus_ops 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,
+};
+
+/* Registering the FF-A driver as an SMCCC feature driver */
+
+ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
+	.driver_name = FFA_DRV_NAME,
+	.is_supported = arm_ffa_is_supported,
+};
+
+/* Declaring the FF-A driver under UCLASS_FFA */
+
+U_BOOT_DRIVER(arm_ffa) = {
+	.name		= FFA_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.flags		= DM_REMOVE_OS_PREPARE,
+	.ops		= &ffa_ops,
+};
diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
new file mode 100644
index 0000000000..4338f9c9b1
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
@@ -0,0 +1,14 @@
+/* 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/include/arm_ffa.h b/include/arm_ffa.h
new file mode 100644
index 0000000000..db9b1be995
--- /dev/null
+++ b/include/arm_ffa.h
@@ -0,0 +1,213 @@
+/* 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 __ARM_FFA_H
+#define __ARM_FFA_H
+
+#include <linux/printk.h>
+
+/*
+ * This header is public. It can be used by clients to access
+ * data structures and definitions they need
+ */
+
+/*
+ * struct ffa_partition_info - Partition information descriptor
+ * @id:	Partition ID
+ * @exec_ctxt:	Execution context count
+ * @properties:	Partition properties
+ *
+ * Data structure containing information about partitions instantiated in the system
+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
+ */
+struct ffa_partition_info {
+	u16 id;
+	u16 exec_ctxt;
+/* partition supports receipt of direct requests */
+#define FFA_PARTITION_DIRECT_RECV	BIT(0)
+/* partition can send direct requests. */
+#define FFA_PARTITION_DIRECT_SEND	BIT(1)
+/* partition can send and receive indirect messages. */
+#define FFA_PARTITION_INDIRECT_MSG	BIT(2)
+	u32 properties;
+};
+
+/*
+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
+ * @a1-4:	32-bit words access to the UUID data
+ *
+ */
+struct ffa_partition_uuid {
+	u32 a1; /* w1 */
+	u32 a2; /* w2 */
+	u32 a3; /* w3 */
+	u32 a4; /* w4 */
+};
+
+/**
+ * struct ffa_partition_desc - the secure partition descriptor
+ * @info:	partition information
+ * @sp_uuid:	the secure partition UUID
+ *
+ * Each partition has its descriptor containing the partitions information and the UUID
+ */
+struct ffa_partition_desc {
+	struct ffa_partition_info info;
+	struct ffa_partition_uuid sp_uuid;
+};
+
+/*
+ * struct ffa_send_direct_data - Data structure hosting the data
+ *                                       used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * @data0-4:	Data read/written from/to x3-x7 registers
+ *
+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
+ * or read from FFA_MSG_SEND_DIRECT_RESP
+ */
+
+/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
+struct ffa_send_direct_data {
+	ulong data0; /* w3/x3 */
+	ulong data1; /* w4/x4 */
+	ulong data2; /* w5/x5 */
+	ulong data3; /* w6/x6 */
+	ulong data4; /* w7/x7 */
+};
+
+struct udevice;
+
+/**
+ * struct ffa_bus_ops - Operations for FF-A
+ * @partition_info_get:	callback for the FFA_PARTITION_INFO_GET
+ * @sync_send_receive:	callback for the FFA_MSG_SEND_DIRECT_REQ
+ * @rxtx_unmap:	callback for the FFA_RXTX_UNMAP
+ *
+ * The data structure providing all the operations supported by the driver.
+ * This structure is EFI runtime resident.
+ */
+struct ffa_bus_ops {
+	int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
+				  u32 *sp_count, struct ffa_partition_desc **sp_descs);
+	int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg,
+				 bool is_smc64);
+	int (*rxtx_unmap)(struct udevice *dev);
+};
+
+#define ffa_get_ops(dev)        ((struct ffa_bus_ops *)(dev)->driver->ops)
+
+/**
+ * ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
+ * Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
+ */
+int ffa_rxtx_unmap(struct udevice *dev);
+
+/**
+ * ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
+ * @dev: The arm_ffa bus device
+ *
+ * This function implements FFA_RXTX_UNMAP FF-A function
+ * to unmap the RX/TX buffers
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev);
+
+/**
+ * ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
+ * Please see ffa_msg_send_direct_req_hdlr() description for more details.
+ */
+int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
+			  struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @dev: The arm_ffa bus device
+ * @dst_part_id: destination partition ID
+ * @msg: pointer to the message data preallocated by the client (in/out)
+ * @is_smc64: select 64-bit or 32-bit FF-A ABI
+ *
+ * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
+ * The response from the secure partition is handled by reading the
+ * FFA_MSG_SEND_DIRECT_RESP arguments.
+ *
+ * The maximum size of the data that can be exchanged is 40 bytes which is
+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
+				 struct ffa_send_direct_data *msg, bool is_smc64);
+
+/**
+ * ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
+ * Please see ffa_get_partitions_info_hdlr() description for more details.
+ */
+int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
+			   u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+/**
+ * ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
+ *	@uuid_str: pointer to the UUID string
+ *	@sp_count: address of the variable containing the number of partitions matching the UUID
+ *			 The variable is set by the driver
+ *	@sp_descs: address of the descriptors of the partitions matching the UUID
+ *			 The address is set by the driver
+ *
+ * Return the number of partitions and their descriptors matching the UUID
+ *
+ * Query the secure partition data from uc_priv.
+ * If not found, invoke FFA_PARTITION_INFO_GET
+ * FF-A function to query the partition information from secure world.
+ *
+ * A client of the FF-A driver should know the UUID of the service it wants to
+ * access. It should use the UUID to request the FF-A driver to provide the
+ * partition(s) information of the service. The FF-A driver uses
+ * PARTITION_INFO_GET to obtain this information. This is implemented through
+ * ffa_get_partitions_info_hdlr() function.
+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
+ * They are not saved (already done). We only update the UUID in the cached area.
+ * This assumes that partitions data does not change in the secure world.
+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
+ * the information in the FF-A driver is to accommodate discovery after
+ * ExitBootServices().
+ *
+ * Return:
+ *
+ * @sp_count: the number of partitions
+ * @sp_descs: address of the partitions descriptors
+ *
+ * On success 0 is returned. Otherwise, failure
+ */
+int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
+				 u32 *sp_count, struct ffa_partition_desc **sp_descs);
+
+struct ffa_priv;
+
+/**
+ * ffa_set_smc_conduit() - Set the SMC conduit
+ * @dev: The FF-A bus device
+ *
+ * Selects the SMC conduit by setting the FF-A ABI invoke function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_set_smc_conduit(struct udevice *dev);
+
+#endif
diff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h
new file mode 100644
index 0000000000..d564c33c64
--- /dev/null
+++ b/include/arm_ffa_priv.h
@@ -0,0 +1,246 @@
+/* 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 __ARM_FFA_PRV_H
+#define __ARM_FFA_PRV_H
+
+#include <mapmem.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+
+/* This header is exclusively used by the FF-A Uclass and FF-A driver(s) */
+
+/* Arm FF-A driver name */
+#define FFA_DRV_NAME "arm_ffa"
+
+/* The FF-A SMC function definitions */
+
+#if CONFIG_IS_ENABLED(SANDBOX)
+
+/* Providing Arm SMCCC declarations to sandbox */
+
+/**
+ * struct sandbox_smccc_1_2_regs - emulated SMC call arguments or results
+ * @a0-a17 argument values from registers 0 to 17
+ */
+struct sandbox_smccc_1_2_regs {
+	ulong a0;
+	ulong a1;
+	ulong a2;
+	ulong a3;
+	ulong a4;
+	ulong a5;
+	ulong a6;
+	ulong a7;
+	ulong a8;
+	ulong a9;
+	ulong a10;
+	ulong a11;
+	ulong a12;
+	ulong a13;
+	ulong a14;
+	ulong a15;
+	ulong a16;
+	ulong a17;
+};
+
+typedef struct sandbox_smccc_1_2_regs ffa_value_t;
+
+#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))
+
+#else
+/* CONFIG_ARM64 */
+#include <linux/arm-smccc.h>
+typedef struct arm_smccc_1_2_regs ffa_value_t;
+#endif
+
+/* Defining the function pointer type for the function executing the FF-A ABIs */
+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)
+#define MINOR_VERSION_MASK		GENMASK(15, 0)
+#define GET_FFA_MAJOR_VERSION(x)		\
+				((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
+#define GET_FFA_MINOR_VERSION(x)		\
+				((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
+#define PACK_VERSION_INFO(major, minor)			\
+	(FIELD_PREP(MAJOR_VERSION_MASK, (major)) |	\
+	 FIELD_PREP(MINOR_VERSION_MASK, (minor)))
+
+#define FFA_MAJOR_VERSION		(1)
+#define FFA_MINOR_VERSION		(0)
+#define FFA_VERSION_1_0		\
+			PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
+
+/* Endpoint ID mask (u-boot endpoint ID) */
+
+#define GET_SELF_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define GET_SELF_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
+
+#define PREP_SELF_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define PREP_SELF_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
+
+/* Partition endpoint ID mask  (partition with which u-boot communicates with) */
+
+#define PREP_PART_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_PART_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
+
+/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */
+
+#define FFA_SMC(calling_convention, func_num)				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention),	\
+			   ARM_SMCCC_OWNER_STANDARD, (func_num))
+
+#define FFA_SMC_32(func_num)				FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
+#define FFA_SMC_64(func_num)				FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
+
+enum ffa_abis {
+	FFA_ERROR                 = 0x60,
+	FFA_SUCCESS               = 0x61,
+	FFA_INTERRUPT             = 0x62,
+	FFA_VERSION               = 0x63,
+	FFA_FEATURES              = 0x64,
+	FFA_RX_RELEASE            = 0x65,
+	FFA_RXTX_MAP              = 0x66,
+	FFA_RXTX_UNMAP            = 0x67,
+	FFA_PARTITION_INFO_GET    = 0x68,
+	FFA_ID_GET                = 0x69,
+	FFA_RUN                   = 0x6d,
+	FFA_MSG_SEND_DIRECT_REQ   = 0x6f,
+	FFA_MSG_SEND_DIRECT_RESP  = 0x70,
+
+	/* To be updated when adding new FFA IDs */
+	FFA_FIRST_ID              = FFA_ERROR, /* Lowest number ID */
+	FFA_LAST_ID               = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
+};
+
+enum ffa_abi_errcode {
+	NOT_SUPPORTED = 1,
+	INVALID_PARAMETERS,
+	NO_MEMORY,
+	BUSY,
+	INTERRUPTED,
+	DENIED,
+	RETRY,
+	ABORTED,
+	MAX_NUMBER_FFA_ERR
+};
+
+extern int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR];
+
+/* Container structure and helper macros to map between an FF-A error and relevant error log */
+struct ffa_abi_errmap {
+	char *err_str[MAX_NUMBER_FFA_ERR];
+};
+
+#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
+#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
+
+/**
+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
+ * for the RX/TX buffers
+ */
+enum ffa_rxtx_buf_sizes {
+	RXTX_4K,
+	RXTX_64K,
+	RXTX_16K
+};
+
+/**
+ * struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses
+ * @rxbuf:	virtual address of the RX buffer
+ * @txbuf:	virtual address of the TX buffer
+ * @rxtx_min_pages:	RX/TX buffers minimum size in pages
+ *
+ * Hosts the virtual addresses of the mapped RX/TX buffers
+ * These addresses are used by the FF-A functions that use the RX/TX buffers
+ */
+struct ffa_rxtxpair {
+	void *rxbuf; /* Virtual address returned by memalign */
+	void *txbuf; /* Virtual address returned by memalign */
+	size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */
+};
+
+struct ffa_partition_desc;
+
+/**
+ * struct ffa_partitions - descriptors for all secure partitions
+ * @count:	The number of partitions descriptors
+ * @descs	The partitions descriptors table
+ *
+ * Contains the partitions descriptors table
+ */
+struct ffa_partitions {
+	u32 count;
+	struct ffa_partition_desc *descs; /* Virtual address */
+};
+
+/**
+ * struct ffa_priv - the driver private data structure
+ *
+ * @fwk_version:	FF-A framework version
+ * @emul:	FF-A sandbox emulator
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ *
+ * The device private data structure containing all the
+ * data read from secure world.
+ */
+struct ffa_priv {
+	u32 fwk_version;
+	struct udevice *emul;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+};
+
+/**
+ * ffa_get_version_hdlr() - FFA_VERSION handler function
+ * @dev: The FF-A bus device
+ *
+ * Implement FFA_VERSION FF-A function
+ * to get from the secure world the FF-A framework version
+ * FFA_VERSION is used to discover the FF-A framework.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_get_version_hdlr(struct udevice *dev);
+
+/**
+ * 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 low level SMC implementation.
+ * This function should be implemented by the user driver.
+ */
+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 307ad6931c..3c6af2e3d2 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -4,6 +4,11 @@
  *
  * (C) Copyright 2012
  * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _DM_UCLASS_ID_H
@@ -57,6 +62,7 @@ enum uclass_id {
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_EXTCON,		/* External Connector Class */
+	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v19 5/9] arm_ffa: introduce sandbox FF-A support
  2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                       ` (3 preceding siblings ...)
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 4/9] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
@ 2023-08-04 13:33                                                                                                                                                                                     ` Abdellatif El Khlifi
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 6/9] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
                                                                                                                                                                                                       ` (5 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-04 13:33 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, sjg, u-boot, Heinrich Schuchardt

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>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove reparenting by making the emulator parent of the FF-A device in the DT
* add invoke_ffa_fn()
* address nits

v11:

* rename ffa_try_discovery() to sandbox_ffa_discover()
* rename sandbox_ffa_query_core_state() to sandbox_query_ffa_emul_state()
* store the sandbox emulator pointer in the FF-A device uc_priv (struct ffa_priv)
* set the emulator as parent of the sandbox FF-A device

v10:

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

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

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

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

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

v1: introduce the sandbox driver

MAINTAINERS                                   |   3 +-
 arch/sandbox/dts/sandbox.dtsi                 |   9 +
 arch/sandbox/dts/test.dts                     |   8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |  72 ++
 .../include/asm/sandbox_arm_ffa_priv.h        | 121 +++
 configs/sandbox64_defconfig                   |   1 +
 configs/sandbox_defconfig                     |   1 +
 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, 1081 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 4fd5768de0..63cf37290c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,10 +269,11 @@ 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:	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/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..96b5404991 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1820,6 +1820,14 @@
 	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..72ea3d21ab 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -260,3 +260,4 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 1ec44d5b33..8269bec879 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -344,3 +344,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index df18948774..792898321a 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.
@@ -203,6 +206,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
+
 Example of boot logs with FF-A enabled
 --------------------------------------
 
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 9200c8028b..fc668c109d 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
 	select LIB_UUID
 	select DEVRES
 	help
@@ -32,5 +32,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


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v19 6/9] arm_ffa: introduce sandbox test cases for UCLASS_FFA
  2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                       ` (4 preceding siblings ...)
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 5/9] arm_ffa: introduce sandbox " Abdellatif El Khlifi
@ 2023-08-04 13:33                                                                                                                                                                                     ` Abdellatif El Khlifi
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 7/9] arm_ffa: introduce armffa command Abdellatif El Khlifi
                                                                                                                                                                                                       ` (4 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-04 13:33 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, sjg, u-boot, Heinrich Schuchardt

Add functional test cases for the FF-A support

These tests rely on the FF-A sandbox emulator and FF-A
sandbox driver which help in inspecting the FF-A communication.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v12:

* remove use of dscvry_info
* drop use of calloc when querying SPs
* address nits

v11:

* drop unmapping test (taken care of by the DM when removing the device)
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* replace CONFIG_SANDBOX_FFA with CONFIG_ARM_FFA_TRANSPORT
* address nits

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

v8:

  * update partition_info_get() second argument to be an SP count
  * pass NULL device pointer to the FF-A bus discovery and operations

v7: set the tests to use 64-bit direct messaging

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

v1: introduce sandbox tests

MAINTAINERS            |   1 +
 doc/arch/arm64.ffa.rst |   1 +
 test/dm/Makefile       |   3 +-
 test/dm/ffa.c          | 261 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 265 insertions(+), 1 deletion(-)
 create mode 100644 test/dm/ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 63cf37290c..b6d7263010 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -274,6 +274,7 @@ F:	arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
 F:	doc/arch/arm64.ffa.rst
 F:	drivers/firmware/arm-ffa/
 F:	include/arm_ffa.h
+F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 792898321a..71606373f9 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -37,6 +37,7 @@ The U-Boot FF-A support provides the following parts:
   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.
+- Sandbox FF-A test cases.
 
 FF-A and SMC specifications
 -------------------------------------------
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 3799b1ae8f..7ed00733c1 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
-# Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 obj-$(CONFIG_UT_DM) += test-dm.o
 
@@ -92,6 +92,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o
 obj-$(CONFIG_ACPI_PMC) += pmc.o
 obj-$(CONFIG_DM_PMIC) += pmic.o
 obj-$(CONFIG_DM_PWM) += pwm.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += ffa.o
 obj-$(CONFIG_QFW) += qfw.o
 obj-$(CONFIG_RAM) += ram.o
 obj-y += regmap.o
diff --git a/test/dm/ffa.c b/test/dm/ffa.c
new file mode 100644
index 0000000000..6912666bb4
--- /dev/null
+++ b/test/dm/ffa.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Functional tests for UCLASS_FFA  class
+ *
+ * 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 <console.h>
+#include <dm.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <asm/sandbox_arm_ffa_priv.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Functional tests for the UCLASS_FFA */
+
+static int check_fwk_version(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	struct ffa_sandbox_data func_data;
+	u32 fwk_version = 0;
+
+	func_data.data0 = &fwk_version;
+	func_data.data0_size = sizeof(fwk_version);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_VERSION, &func_data));
+	ut_asserteq(uc_priv->fwk_version, fwk_version);
+
+	return 0;
+}
+
+static int check_endpoint_id(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_asserteq(0, uc_priv->id);
+
+	return 0;
+}
+
+static int check_rxtxbuf(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assertnonnull(uc_priv->pair.rxbuf);
+	ut_assertnonnull(uc_priv->pair.txbuf);
+
+	return 0;
+}
+
+static int check_features(struct ffa_priv *uc_priv, struct unit_test_state *uts)
+{
+	ut_assert(uc_priv->pair.rxtx_min_pages == RXTX_4K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_16K ||
+		  uc_priv->pair.rxtx_min_pages == RXTX_64K);
+
+	return 0;
+}
+
+static int check_rxbuf_mapped_flag(u32 queried_func_id,
+				   u8 rxbuf_mapped,
+				   struct unit_test_state *uts)
+{
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+		ut_asserteq(1, rxbuf_mapped);
+		break;
+	case FFA_RXTX_UNMAP:
+		ut_asserteq(0, rxbuf_mapped);
+		break;
+	default:
+		ut_assert(false);
+	}
+
+	return 0;
+}
+
+static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts)
+{
+	ut_asserteq(0, rxbuf_owned);
+
+	return 0;
+}
+
+static int  test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts)
+{
+	struct ffa_send_direct_data msg;
+	u8 cnt;
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++)
+		ut_asserteq_64(-1UL, ((u64 *)&msg)[cnt]);
+
+	return 0;
+}
+
+static int test_partitions_and_comms(const char *service_uuid,
+				     struct unit_test_state *uts)
+{
+	struct ffa_partition_desc *descs;
+	u32 count, i, j, valid_sps = 0;
+	struct udevice *dev;
+	struct ffa_sandbox_data func_data;
+	struct ffa_partitions *partitions;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get from the driver the count and information of the SPs matching the UUID */
+	ut_assertok(ffa_partition_info_get(dev, service_uuid, &count, &descs));
+
+	/* Make sure the count is correct */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+
+	/* SPs found , verify the partitions information */
+
+	func_data.data0 = &partitions;
+	func_data.data0_size = sizeof(struct ffa_partitions *);
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_PARTITION_INFO_GET, &func_data));
+
+	for (i = 0; i < count ; i++) {
+		for (j = 0;
+		     j < partitions->count;
+		     j++) {
+			if (descs[i].info.id ==
+			   partitions->descs[j].info.id) {
+				valid_sps++;
+				ut_asserteq_mem(&descs[i],
+						&partitions->descs[j],
+						sizeof(struct ffa_partition_desc));
+				/* Send and receive data from the current partition */
+				test_ffa_msg_send_direct_req(descs[i].info.id, uts);
+			}
+		}
+	}
+
+	/* Verify expected partitions found in the emulated secure world */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, valid_sps);
+
+	return 0;
+}
+
+static int dm_test_ffa_ack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	struct ffa_sandbox_data func_data;
+	u8 rxbuf_flag = 0;
+	const char *svc1_uuid = SANDBOX_SERVICE1_UUID;
+	const char *svc2_uuid = SANDBOX_SERVICE2_UUID;
+	struct udevice *dev;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Test FFA_VERSION */
+	check_fwk_version(uc_priv, uts);
+
+	/* Test FFA_ID_GET */
+	check_endpoint_id(uc_priv, uts);
+
+	/* Test FFA_FEATURES */
+	check_features(uc_priv, uts);
+
+	/*  Test RX/TX buffers */
+	check_rxtxbuf(uc_priv, uts);
+
+	/* Test FFA_RXTX_MAP */
+	func_data.data0 = &rxbuf_flag;
+	func_data.data0_size = sizeof(rxbuf_flag);
+
+	rxbuf_flag = 0;
+	sandbox_query_ffa_emul_state(FFA_RXTX_MAP, &func_data);
+	check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc1_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data);
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	/* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */
+	test_partitions_and_comms(svc2_uuid, uts);
+
+	/* Test FFA_RX_RELEASE */
+	rxbuf_flag = 1;
+	ut_assertok(sandbox_query_ffa_emul_state(FFA_RX_RELEASE, &func_data));
+	check_rxbuf_release_flag(rxbuf_flag, uts);
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+static int dm_test_ffa_nack(struct unit_test_state *uts)
+{
+	struct ffa_priv *uc_priv;
+	const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID;
+	const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID;
+	const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID;
+	struct ffa_send_direct_data msg;
+	int ret;
+	u32 count;
+	u16 part_id = 0;
+	struct udevice *dev;
+	struct ffa_partition_desc *descs = NULL;
+
+	/* Test probing the sandbox FF-A bus */
+	ut_assertok(uclass_first_device_err(UCLASS_FFA, &dev));
+
+	/* Get a pointer to the sandbox FF-A bus private data */
+	uc_priv = dev_get_uclass_priv(dev);
+
+	/* Make sure the private data pointer is retrieved */
+	ut_assertnonnull(uc_priv);
+
+	/* Query partitions count using  invalid arguments */
+	ret = ffa_partition_info_get(dev, NULL, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, NULL, NULL);
+	ut_asserteq(-EINVAL, ret);
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, NULL);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID  string */
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid_str, &count, &descs);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Query partitions count using an invalid UUID (no matching SP) */
+	count = 0;
+	ret = ffa_partition_info_get(dev, unvalid_svc_uuid, &count, &descs);
+	ut_asserteq(0, count);
+
+	/* Query partitions data using a valid UUID */
+	count = 0;
+	ut_assertok(ffa_partition_info_get(dev, valid_svc_uuid, &count, &descs));
+	/* Make sure partitions are detected */
+	ut_asserteq(SANDBOX_SP_COUNT_PER_VALID_SERVICE, count);
+	ut_assertnonnull(descs);
+
+	/* Send data to an invalid partition */
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	ut_asserteq(-EINVAL, ret);
+
+	/* Send data to a valid partition */
+	part_id = uc_priv->partitions.descs[0].info.id;
+	ut_assertok(ffa_sync_send_receive(dev, part_id, &msg, 1));
+
+	return 0;
+}
+
+DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v19 7/9] arm_ffa: introduce armffa command
  2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                       ` (5 preceding siblings ...)
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 6/9] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
@ 2023-08-04 13:33                                                                                                                                                                                     ` Abdellatif El Khlifi
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 8/9] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
                                                                                                                                                                                                       ` (3 subsequent siblings)
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-04 13:33 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, sjg, u-boot, Heinrich Schuchardt

Provide armffa command showcasing the use of the U-Boot FF-A support

armffa is a command showcasing how to invoke FF-A operations.
This provides a guidance to the client developers on how to
call the FF-A bus interfaces. The command also allows to gather secure
partitions information and ping these  partitions. The command is also
helpful in testing the communication with secure partitions.

For more details please refer to the command documentation [1].

A Sandbox test is provided for the armffa command.

[1]: doc/usage/cmd/armffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>

---

Changelog:
===============

v18:

Simon:

* Combining the commits of the command and the test case

v15:

Simon:

* armffa.c : integrate PHYS_ADDR_LN

v14:

Ilias:

* address nits
* in do_ffa_ping() reject the SP ID if it's 0
* use PHYS_ADDR_LN in formatting the physical addresses

v12:

* add subcommands argument checks
* usage documentation: update command return codes
* remove calloc when querying SPs
* address nits

v11:

* use U_BOOT_CMD_WITH_SUBCMDS
* address nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* address nits

v9:

* remove manual FF-A discovery and use DM
* use DM class APIs to probe and interact with the FF-A bus
* add doc/usage/cmd/armffa.rst

v8:

* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* adapt do_ffa_dev_list() following the recent update on
  uclass_first_device/uclass_next_device functions (they return void now)
* set armffa command to use 64-bit direct messaging

v4:

* remove pattern data in do_ffa_msg_send_direct_req

v3:

* use the new driver interfaces (partition_info_get, sync_send_receive)
  in armffa command

v2:

* replace use of ffa_helper_init_device function by
 ffa_helper_bus_discover

v1:

* introduce armffa command

MAINTAINERS                      |   3 +
 cmd/Kconfig                      |  10 ++
 cmd/Makefile                     |   1 +
 cmd/armffa.c                     | 202 +++++++++++++++++++++++++++++++
 doc/arch/arm64.ffa.rst           |   9 ++
 doc/usage/cmd/armffa.rst         |  94 ++++++++++++++
 doc/usage/index.rst              |   1 +
 drivers/firmware/arm-ffa/Kconfig |   1 +
 test/cmd/Makefile                |   2 +
 test/cmd/armffa.c                |  33 +++++
 10 files changed, 356 insertions(+)
 create mode 100644 cmd/armffa.c
 create mode 100644 doc/usage/cmd/armffa.rst
 create mode 100644 test/cmd/armffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index b6d7263010..bd3dba3d95 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -271,9 +271,12 @@ 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:	test/cmd/armffa.c
 F:	test/dm/ffa.c
 
 ARM FREESCALE IMX
diff --git a/cmd/Kconfig b/cmd/Kconfig
index c1941849f9..da8569b417 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -935,6 +935,16 @@ endmenu
 
 menu "Device access commands"
 
+config CMD_ARMFFA
+	bool "Arm FF-A test command"
+	depends on ARM_FFA_TRANSPORT
+	help
+	  Provides a test command for the FF-A support
+	  supported options:
+		- Listing the partition(s) info
+		- Sending a data pattern to the specified partition
+		- Displaying the arm_ffa device info
+
 config CMD_ARMFLASH
 	#depends on FLASH_CFI_DRIVER
 	bool "armflash"
diff --git a/cmd/Makefile b/cmd/Makefile
index 6c37521b4e..7d20a85a46 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,7 @@ obj-y += panic.o
 obj-y += version.o
 
 # command
+obj-$(CONFIG_CMD_ARMFFA) += armffa.o
 obj-$(CONFIG_CMD_2048) += 2048.o
 obj-$(CONFIG_CMD_ACPI) += acpi.o
 obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
diff --git a/cmd/armffa.c b/cmd/armffa.c
new file mode 100644
index 0000000000..7e6eafc03a
--- /dev/null
+++ b/cmd/armffa.c
@@ -0,0 +1,202 @@
+// 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 <command.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <stdlib.h>
+#include <asm/io.h>
+
+/* Select the right physical address formatting according to the platform */
+#ifdef CONFIG_PHYS_64BIT
+#define PhysAddrLength "ll"
+#else
+#define PhysAddrLength ""
+#endif
+#define PHYS_ADDR_LN "%" PhysAddrLength "x"
+
+/**
+ * ffa_get_dev() - Return the FF-A device
+ * @devp:	pointer to the FF-A device
+ *
+ * Search for the FF-A device.
+ *
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+static int ffa_get_dev(struct udevice **devp)
+{
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, devp);
+	if (ret) {
+		log_err("Cannot find FF-A bus device\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * do_ffa_getpart() - implementation of the getpart subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query a secure partition information. The secure partition UUID is provided
+ * as an argument. The function uses the arm_ffa driver
+ * partition_info_get operation which implements FFA_PARTITION_INFO_GET
+ * ABI to retrieve the data. The input UUID string is expected to be in big
+ * endian format.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc,
+			  char *const argv[])
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	u32 i;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	/* Ask the driver to fill the buffer with the SPs info */
+
+	ret = ffa_partition_info_get(dev, argv[1], &count, &descs);
+	if (ret) {
+		log_err("Failure in querying partition(s) info (error code: %d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	/* SPs found , show the partition information */
+	for (i = 0; i < count ; i++) {
+		log_info("Partition: id = %x , exec_ctxt %x , properties %x\n",
+			 descs[i].info.id,
+			 descs[i].info.exec_ctxt,
+			 descs[i].info.properties);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_ffa_ping() - implementation of the ping subcommand
+ * @cmdtp:		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Send data to a secure partition. The secure partition UUID is provided
+ * as an argument. Use the arm_ffa driver sync_send_receive operation
+ * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct ffa_send_direct_data msg = {
+			.data0 = 0xaaaaaaaa,
+			.data1 = 0xbbbbbbbb,
+			.data2 = 0xcccccccc,
+			.data3 = 0xdddddddd,
+			.data4 = 0xeeeeeeee,
+	};
+	u16 part_id;
+	int ret;
+	struct udevice *dev;
+
+	if (argc != 2) {
+		log_err("Missing argument\n");
+		return CMD_RET_USAGE;
+	}
+
+	part_id = strtoul(argv[1], NULL, 16);
+	if (!part_id) {
+		log_err("Partition ID can not be 0\n");
+		return CMD_RET_USAGE;
+	}
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	ret = ffa_sync_send_receive(dev, part_id, &msg, 1);
+	if (!ret) {
+		u8 cnt;
+
+		log_info("SP response:\n[LSB]\n");
+		for (cnt = 0;
+		     cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64);
+		     cnt++)
+			log_info("%llx\n", ((u64 *)&msg)[cnt]);
+		return CMD_RET_SUCCESS;
+	}
+
+	log_err("Sending direct request error (%d)\n", ret);
+	return CMD_RET_FAILURE;
+}
+
+/**
+ *do_ffa_devlist() - implementation of the devlist subcommand
+ * @cmdtp: [in]		Command Table
+ * @flag:		flags
+ * @argc:		number of arguments
+ * @argv:		arguments
+ *
+ * Query the device belonging to the UCLASS_FFA
+ * class.
+ *
+ * Return:
+ *
+ * CMD_RET_SUCCESS: on success, otherwise failure
+ */
+static int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = ffa_get_dev(&dev);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	log_info("device %s, addr " PHYS_ADDR_LN ", driver %s, ops " PHYS_ADDR_LN "\n",
+		 dev->name,
+		 map_to_sysmem(dev),
+		 dev->driver->name,
+		 map_to_sysmem(dev->driver->ops));
+
+	return CMD_RET_SUCCESS;
+}
+
+static char armffa_help_text[] =
+	"getpart <partition UUID>\n"
+	"       - lists the partition(s) info\n"
+	"ping <partition ID>\n"
+	"       - sends a data pattern to the specified partition\n"
+	"devlist\n"
+	"       - displays information about the FF-A device/driver\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(armffa, "Arm FF-A test command", armffa_help_text,
+			U_BOOT_SUBCMD_MKENT(getpart, 2, 1, do_ffa_getpart),
+			U_BOOT_SUBCMD_MKENT(ping, 2, 1, do_ffa_ping),
+			U_BOOT_SUBCMD_MKENT(devlist, 1, 1, do_ffa_devlist));
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 71606373f9..325fb80346 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -120,6 +120,8 @@ At this stage the FF-A bus is registered with the DM and can be interacted with
 the DM APIs.
 
 Clients are able to probe then use the FF-A bus by calling uclass_first_device().
+Please refer to the armffa command implementation as an example of how to probe
+and interact with the FF-A bus.
 
 When calling uclass_first_device(), the FF-A driver is probed and ends up calling
 ffa_do_probe() provided by the Uclass which does the following:
@@ -219,6 +221,13 @@ Relationship between the sandbox emulator and the FF-A device
    ffa_emul      0  [ + ]   sandbox_ffa_emul      `-- arm-ffa-emul
     ffa                  0  [    ]   sandbox_arm_ffa               `-- sandbox-arm-ffa
 
+The armffa command
+-----------------------------------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke the driver operations.
+
+Please refer the command documentation at :doc:`../usage/cmd/armffa`
+
 Example of boot logs with FF-A enabled
 --------------------------------------
 
diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst
new file mode 100644
index 0000000000..13fa90c129
--- /dev/null
+++ b/doc/usage/cmd/armffa.rst
@@ -0,0 +1,94 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+
+armffa command
+==============
+
+Synopsis
+--------
+
+::
+
+   armffa [sub-command] [arguments]
+
+   sub-commands:
+
+        getpart [partition UUID]
+
+            lists the partition(s) info
+
+        ping [partition ID]
+
+            sends a data pattern to the specified partition
+
+        devlist
+
+            displays information about the FF-A device/driver
+
+Description
+-----------
+
+armffa is a command showcasing how to use the FF-A bus and how to invoke its operations.
+
+This provides a guidance to the client developers on how to call the FF-A bus interfaces.
+
+The command also allows to gather secure partitions information and ping these  partitions.
+
+The command is also helpful in testing the communication with secure partitions.
+
+Example
+-------
+
+The following examples are run on Corstone-1000 platform.
+
+* ping
+
+::
+
+   corstone1000# armffa ping 0x8003
+   SP response:
+   [LSB]
+   fffffffe
+   0
+   0
+   0
+   0
+
+* ping (failure case)
+
+::
+
+   corstone1000# armffa ping 0
+   Sending direct request error (-22)
+
+* getpart
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d
+   Partition: id = 8003 , exec_ctxt 1 , properties 3
+
+* getpart (failure case)
+
+::
+
+   corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd7221
+   INVALID_PARAMETERS: Unrecognized UUID
+   Failure in querying partitions count (error code: -22)
+
+* devlist
+
+::
+
+   corstone1000# armffa devlist
+   device name arm_ffa, dev 00000000fdf41c30, driver name arm_ffa, ops 00000000fffc0e98
+
+Configuration
+-------------
+
+The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y.
+
+Return value
+------------
+
+The return value $? is 0 (true) on success, 1 (false) on failure.
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 388e59f173..e462de2806 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -22,6 +22,7 @@ Shell commands
 
    cmd/acpi
    cmd/addrmap
+   cmd/armffa
    cmd/askenv
    cmd/base
    cmd/bdinfo
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index fc668c109d..d75f8b53fd 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT
 	depends on DM && (ARM64 || SANDBOX)
 	select ARM_SMCCC if !SANDBOX
 	select ARM_SMCCC_FEATURES if !SANDBOX
+	imply CMD_ARMFFA
 	select LIB_UUID
 	select DEVRES
 	help
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index a3cf983739..6e3d7e919e 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Copyright (c) 2013 Google, Inc
+# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 
 ifdef CONFIG_HUSH_PARSER
 obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
@@ -24,6 +25,7 @@ obj-$(CONFIG_CMD_SEAMA) += seama.o
 ifdef CONFIG_SANDBOX
 obj-$(CONFIG_CMD_READ) += rw.o
 obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o
 endif
 obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o
 obj-$(CONFIG_CMD_WGET) += wget.o
diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c
new file mode 100644
index 0000000000..9a44a397e8
--- /dev/null
+++ b/test/cmd/armffa.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for armffa command
+ *
+ * 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 <string.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+/* Basic test of 'armffa' command */
+static int dm_test_armffa_cmd(struct unit_test_state *uts)
+{
+	/* armffa getpart <UUID> */
+	ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0));
+
+	/* armffa ping <ID> */
+	ut_assertok(run_commandf("armffa ping 0x%x", SANDBOX_SP1_ID));
+
+	/* armffa devlist */
+	ut_assertok(run_command("armffa devlist", 0));
+
+	return 0;
+}
+
+DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v19 8/9] arm_ffa: efi: introduce FF-A MM communication
  2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                       ` (6 preceding siblings ...)
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 7/9] arm_ffa: introduce armffa command Abdellatif El Khlifi
@ 2023-08-04 13:33                                                                                                                                                                                     ` Abdellatif El Khlifi
  2023-08-04 18:35                                                                                                                                                                                       ` Tom Rini
  2023-08-07 14:47                                                                                                                                                                                       ` Ilias Apalodimas
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 9/9] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
                                                                                                                                                                                                       ` (2 subsequent siblings)
  10 siblings, 2 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-04 13:33 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, sjg, u-boot, Gowtham Suresh Kumar

Add MM communication support using FF-A transport

This feature allows accessing MM partitions services through
EFI MM communication protocol. MM partitions such as StandAlonneMM
or smm-gateway secure partitions which reside in secure world.

An MM shared buffer and a door bell event are used to exchange
the data.

The data is used by EFI services such as GetVariable()/SetVariable()
and copied from the communication buffer to the MM shared buffer.

The secure partition is notified about availability of data in the
MM shared buffer by an FF-A message (door bell).

On such event, MM SP can read the data and updates the MM shared
buffer with the response data.

The response data is copied back to the communication buffer and
consumed by the EFI subsystem.

MM communication protocol supports FF-A 64-bit direct messaging.

We tested the FF-A MM communication on the Corstone-1000 platform.

We ran the UEFI SCT test suite containing EFI setVariable, getVariable and
getNextVariable tests which involve FF-A MM communication and all tests
are passing with the current changes.

We made the SCT test reports (part of the ACS results) public following the
latest Corstone-1000 platform software release. Please find the test
reports at [1].

[1]: https://gitlab.arm.com/arm-reference-solutions/arm-reference-solutions-test-report/-/tree/master/embedded-a/corstone1000/CORSTONE1000-2023.06/acs_results_fpga.zip

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jens Wiklander <jens.wiklander@linaro.org>

---

Changelog:
===============

v19:

Tom:

* use CONFIG_FFA_SHARED_MM_BUF_* in place of macros

v18:

Ilias, Tom:

* drop the use of configs for the shared MM buffer, put back #ifdefs instead
* add test information to the commit log

v17:

* show a debug message rather than an error when FF-A is not detected

v16:

* lib/efi_loader/Kconfig:
   rather than automatically selecting OPTEE and ARM_FFA_TRANSPORT configs by
   EFI_MM_COMM_TEE, set them as dependencies (Otherwise FF-A will be automatically
   enabled for boards that don't need it).

v15:

Simon:

* replace FFA_SHARED_MM_BUFFER_* defines with configs

v14:

Ilias:

* drop truncating var_payload->size when using FF-A
* map the MM SP return codes to errnos

v13:

* remove FF-A and Optee ifdefs

v12:

* drop use of calloc when querying SPs
* address nits

v11:

* rename select_ffa_mm_comms() to select_mm_comms()
* improve the logic of MM transport selection in mm_communicate()
* addressing nits

v10:

* use the FF-A driver Uclass operations
* use uclass_first_device()
* addressing nits

v9: align how FF-A is used with FF-A discovery through DM

v8:

* isolate the compilation choices between FF-A and OP-TEE
* update partition_info_get() second argument to be an SP count
* pass NULL device pointer to the FF-A bus discovery and operations

v7:

* set the MM door bell event to use 64-bit direct messaging
* issue a compile time error when one of these macros are not found :
  FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
* make mm_sp_svc_uuid static
* replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
* improve use of unmap_sysmem() in ffa_mm_communicate()

v6:

* add FF-A runtime discovery at MM communication level
* drop EFI runtime support for FF-A MM communication
* revert the changes in include/mm_communication.h for
  efi_mm_communicate_header and smm_variable_access structures

v4:

* use the new FF-A driver interfaces
* discover MM partitions at runtime
* copy FF-A driver private data to EFI runtime section at
  ExitBootServices()
* drop use of FFA_ERR_STAT_SUCCESS error code
* replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
  in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
* revert the error log in mm_communicate() in case of failure
* remove packed attribute from efi_mm_communicate_header and
  smm_variable_communicate_header

v2:

* set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings

v1:

* introduce FF-A MM communication

include/mm_communication.h        |  17 ++
 lib/efi_loader/Kconfig            |  39 ++++-
 lib/efi_loader/efi_variable_tee.c | 270 +++++++++++++++++++++++++++++-
 3 files changed, 320 insertions(+), 6 deletions(-)

diff --git a/include/mm_communication.h b/include/mm_communication.h
index e65fbde60d..f38f1a5344 100644
--- a/include/mm_communication.h
+++ b/include/mm_communication.h
@@ -6,6 +6,9 @@
  *  Copyright (c) 2017, Intel Corporation. All rights reserved.
  *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ *    Authors:
+ *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
  */
 
 #ifndef _MM_COMMUNICATION_H_
@@ -13,6 +16,11 @@
 
 #include <part_efi.h>
 
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
+#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
+#endif
+
 /*
  * Interface to the pseudo Trusted Application (TA), which provides a
  * communication channel with the Standalone MM (Management Mode)
@@ -248,4 +256,13 @@ struct smm_variable_var_check_property {
 	u16                       name[];
 };
 
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+/* supported MM transports */
+enum mm_comms_select {
+	MM_COMMS_UNDEFINED,
+	MM_COMMS_FFA,
+	MM_COMMS_OPTEE
+};
+#endif
+
 #endif /* _MM_COMMUNICATION_H_ */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c5835e6ef6..852f9671d8 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -55,13 +55,50 @@ config EFI_VARIABLE_FILE_STORE
 	  stored as file /ubootefi.var on the EFI system partition.
 
 config EFI_MM_COMM_TEE
-	bool "UEFI variables storage service via OP-TEE"
+	bool "UEFI variables storage service via the trusted world"
 	depends on OPTEE
 	help
+	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
+	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+	  When using the u-boot FF-A  driver any MM SP is supported.
+
 	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
 	  variable related operations to that. The application will verify,
 	  authenticate and store the variables on an RPMB.
 
+	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
+	  operations to the MM SP running in the secure world.
+	  A door bell mechanism is used to notify the SP when there is data in the shared
+	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
+	  the door bell event.
+
+config FFA_SHARED_MM_BUF_SIZE
+	int "Memory size of the shared MM communication buffer"
+	depends on EFI_MM_COMM_TEE && ARM_FFA_TRANSPORT
+	help
+	  This defines the size in bytes of the memory area reserved for the shared
+	  buffer used for communication between the MM feature in U-Boot and
+	  the MM SP in secure world.
+	  The size of the memory region must be a multiple of the size of the maximum
+	  translation granule size that is specified in the ID_AA64MMFR0_EL1 System register.
+	  It is assumed that the MM SP knows the size of the shared MM communication buffer.
+
+config FFA_SHARED_MM_BUF_OFFSET
+	int "Data offset in the shared MM communication buffer"
+	depends on EFI_MM_COMM_TEE && ARM_FFA_TRANSPORT
+	help
+	  This defines the offset in bytes of the data read or written to in the shared
+	  buffer by the MM SP.
+
+config FFA_SHARED_MM_BUF_ADDR
+	hex "Define the address of the shared MM communication buffer"
+	depends on EFI_MM_COMM_TEE && ARM_FFA_TRANSPORT
+	help
+	  This defines the address of the shared MM communication buffer
+	  used for communication between the MM feature in U-Boot and
+	  the MM SP in secure world.
+	  It is assumed that the MM SP knows the address of the shared MM communication buffer.
+
 config EFI_VARIABLE_NO_STORE
 	bool "Don't persist non-volatile UEFI variables"
 	help
diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index dfef18435d..09d03c0eee 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -4,16 +4,38 @@
  *
  *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
  *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
+ *  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>
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+#include <arm_ffa.h>
+#endif
+#include <cpu_func.h>
+#include <dm.h>
 #include <efi.h>
 #include <efi_api.h>
 #include <efi_loader.h>
 #include <efi_variable.h>
-#include <tee.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <mm_communication.h>
+#include <tee.h>
+
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+/* MM return codes */
+#define MM_SUCCESS (0)
+#define MM_NOT_SUPPORTED (-1)
+#define MM_INVALID_PARAMETER (-2)
+#define MM_DENIED (-3)
+#define MM_NO_MEMORY (-5)
+
+static const char *mm_sp_svc_uuid = MM_SP_UUID;
+static u16 mm_sp_id;
+#endif
 
 extern struct efi_var_file __efi_runtime_data *efi_var_buf;
 static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
@@ -144,12 +166,238 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
 	return ret;
 }
 
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+/**
+ * ffa_notify_mm_sp() - Announce there is data in the shared buffer
+ *
+ * Notify the MM partition in the trusted world that
+ * data is available in the shared buffer.
+ * This is a blocking call during which trusted world has exclusive access
+ * to the MM shared buffer.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_notify_mm_sp(void)
+{
+	struct ffa_send_direct_data msg = {0};
+	int ret;
+	int sp_event_ret;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
+		return ret;
+	}
+
+	msg.data0 = CONFIG_FFA_SHARED_MM_BUF_OFFSET; /* x3 */
+
+	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
+	if (ret)
+		return ret;
+
+	sp_event_ret = msg.data0; /* x3 */
+
+	switch (sp_event_ret) {
+	case MM_SUCCESS:
+		ret = 0;
+		break;
+	case MM_NOT_SUPPORTED:
+		ret = -EINVAL;
+		break;
+	case MM_INVALID_PARAMETER:
+		ret = -EPERM;
+		break;
+	case MM_DENIED:
+		ret = -EACCES;
+		break;
+	case MM_NO_MEMORY:
+		ret = -EBUSY;
+		break;
+	default:
+		ret = -EACCES;
+	}
+
+	return ret;
+}
+
+/**
+ * ffa_discover_mm_sp_id() - Query the MM partition ID
+ *
+ * Use the FF-A driver to get the MM partition ID.
+ * If multiple partitions are found, use the first one.
+ * This is a boot time function.
+ *
+ * Return:
+ *
+ * 0 on success
+ */
+static int ffa_discover_mm_sp_id(void)
+{
+	u32 count = 0;
+	int ret;
+	struct ffa_partition_desc *descs;
+	struct udevice *dev;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
+		return ret;
+	}
+
+	/* Ask the driver to fill the buffer with the SPs info */
+	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, &descs);
+	if (ret) {
+		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
+		return ret;
+	}
+
+	/* MM SPs found , use the first one */
+
+	mm_sp_id = descs[0].info.id;
+
+	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
+
+	return 0;
+}
+
 /**
- * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
+ * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
+ * @comm_buf:		locally allocated communication buffer used for rx/tx
+ * @dsize:				communication buffer size
+ *
+ * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
+ * that there is data to read from the shared buffer.
+ * Communication with the MM SP is performed using FF-A transport.
+ * On the event, MM SP can read the data from the buffer and
+ * update the MM shared buffer with response data.
+ * The response data is copied back to the communication buffer.
+ *
+ * Return:
+ *
+ * EFI status code
+ */
+static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
+{
+	ulong tx_data_size;
+	int ffa_ret;
+	efi_status_t efi_ret;
+	struct efi_mm_communicate_header *mm_hdr;
+	void *virt_shared_buf;
+
+	if (!comm_buf)
+		return EFI_INVALID_PARAMETER;
+
+	/* Discover MM partition ID at boot time */
+	if (!mm_sp_id && ffa_discover_mm_sp_id()) {
+		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
+		return EFI_UNSUPPORTED;
+	}
+
+	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
+	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
+
+	if (comm_buf_size != tx_data_size || tx_data_size > CONFIG_FFA_SHARED_MM_BUF_SIZE)
+		return EFI_INVALID_PARAMETER;
+
+	/* Copy the data to the shared buffer */
+
+	virt_shared_buf = map_sysmem((phys_addr_t)CONFIG_FFA_SHARED_MM_BUF_ADDR, 0);
+	memcpy(virt_shared_buf, comm_buf, tx_data_size);
+
+	/*
+	 * The secure world might have cache disabled for
+	 * the device region used for shared buffer (which is the case for Optee).
+	 * In this case, the secure world reads the data from DRAM.
+	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 */
+#ifdef CONFIG_ARM64
+	invalidate_dcache_all();
+#endif
+
+	/* Announce there is data in the shared buffer */
+
+	ffa_ret = ffa_notify_mm_sp();
+
+	switch (ffa_ret) {
+	case 0: {
+		ulong rx_data_size;
+		/* Copy the MM SP response from the shared buffer to the communication buffer */
+		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
+			sizeof(efi_guid_t) +
+			sizeof(size_t);
+
+		if (rx_data_size > comm_buf_size) {
+			efi_ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		memcpy(comm_buf, virt_shared_buf, rx_data_size);
+		efi_ret = EFI_SUCCESS;
+		break;
+	}
+	case -EINVAL:
+		efi_ret = EFI_DEVICE_ERROR;
+		break;
+	case -EPERM:
+		efi_ret = EFI_INVALID_PARAMETER;
+		break;
+	case -EACCES:
+		efi_ret = EFI_ACCESS_DENIED;
+		break;
+	case -EBUSY:
+		efi_ret = EFI_OUT_OF_RESOURCES;
+		break;
+	default:
+		efi_ret = EFI_ACCESS_DENIED;
+	}
+
+	unmap_sysmem(virt_shared_buf);
+	return efi_ret;
+}
+
+/**
+ * get_mm_comms() - detect the available MM transport
+ *
+ * Make sure the FF-A bus is probed successfully
+ * which means FF-A communication with secure world works and ready
+ * for use.
+ *
+ * If FF-A bus is not ready, use OPTEE comms.
+ *
+ * Return:
+ *
+ * MM_COMMS_FFA or MM_COMMS_OPTEE
+ */
+static enum mm_comms_select get_mm_comms(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device_err(UCLASS_FFA, &dev);
+	if (ret) {
+		log_debug("EFI: Cannot find FF-A bus device, trying Optee comms\n");
+		return MM_COMMS_OPTEE;
+	}
+
+	return MM_COMMS_FFA;
+}
+#endif
+
+/**
+ * mm_communicate() - Adjust the communication buffer to the MM SP and send
  * it to OP-TEE
  *
- * @comm_buf:		locally allocted communcation buffer
+ * @comm_buf:		locally allocated communication buffer
  * @dsize:		buffer size
+ *
+ * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
+ * The comm_buf format is the same for both partitions.
+ * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
+ * When using the u-boot FF-A  driver, any MM SP is supported.
+ *
  * Return:		status code
  */
 static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
@@ -157,12 +405,24 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
 	efi_status_t ret;
 	struct efi_mm_communicate_header *mm_hdr;
 	struct smm_variable_communicate_header *var_hdr;
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+	enum mm_comms_select mm_comms;
+#endif
 
 	dsize += MM_COMMUNICATE_HEADER_SIZE + MM_VARIABLE_COMMUNICATE_SIZE;
 	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
 	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
 
-	ret = optee_mm_communicate(comm_buf, dsize);
+#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
+	mm_comms = get_mm_comms();
+	if (mm_comms == MM_COMMS_FFA)
+		ret = ffa_mm_communicate(comm_buf, dsize);
+	else
+		ret = optee_mm_communicate(comm_buf, dsize);
+#else
+		ret = optee_mm_communicate(comm_buf, dsize);
+#endif
+
 	if (ret != EFI_SUCCESS) {
 		log_err("%s failed!\n", __func__);
 		return ret;
@@ -697,7 +957,7 @@ void efi_variables_boot_exit_notify(void)
 		ret = EFI_NOT_FOUND;
 
 	if (ret != EFI_SUCCESS)
-		log_err("Unable to notify StMM for ExitBootServices\n");
+		log_err("Unable to notify the MM partition for ExitBootServices\n");
 	free(comm_buf);
 
 	/*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* [PATCH v19 9/9] arm_ffa: efi: corstone1000: enable MM communication
  2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                       ` (7 preceding siblings ...)
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 8/9] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-08-04 13:33                                                                                                                                                                                     ` Abdellatif El Khlifi
  2023-08-04 18:35                                                                                                                                                                                     ` [PATCH v19 0/9] introduce Arm FF-A support Tom Rini
  2023-08-08 19:25                                                                                                                                                                                     ` Tom Rini
  10 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-04 13:33 UTC (permalink / raw)
  To: trini
  Cc: abdellatif.elkhlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, sjg, u-boot

turn on EFI MM communication

On Corstone-1000 platform MM communication between u-boot
and the secure world (Optee) is done using the FF-A bus.

Changes made are generated using savedefconfig.

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>

---

Changelog:
===============

v19:

Tom:

* set CONFIG_FFA_SHARED_MM_BUF_*

v18:

Ilias, Tom:

* drop use of CONFIG_FFA_SHARED_MM_BUF_*

v17:

* use savedefconfig to generate corstone1000_defconfig with FF-A MM comms enabled

v16:

* configs/corstone1000_defconfig:
   enable MM communication by setting the configs: ARM_FFA_TRANSPORT, OPTEE, TEE

v15:

Simon:

* use CONFIG_FFA_SHARED_MM_BUF_* configs in place of FFA_SHARED_MM_BUFFER_*

v13:

* remove FF-A config in the defconfig
   (because it's enabled automatically by CONFIG_EFI_MM_COMM_TEE)

v9:

* update copyright string

v8:

* drop OP-TEE configs from Corstone-1000 defconfig

v7:

* improve the definition of FFA_SHARED_MM_BUFFER_ADDR and
  FFA_SHARED_MM_BUFFER_OFFSET
* update FFA_SHARED_MM_BUFFER_ADDR value

v6:

* corstone-1000: enable optee driver
* corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig

v4:

* corstone-1000: turn on EFI MM communication

configs/corstone1000_defconfig | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
index a8a79fd105..83109b6a7e 100644
--- a/configs/corstone1000_defconfig
+++ b/configs/corstone1000_defconfig
@@ -28,12 +28,10 @@ CONFIG_CMD_FWU_METADATA=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_SYS_BOOTM_LEN=0x800000
 # CONFIG_CMD_XIMG is not set
-CONFIG_CMD_NVMXIP=y
 CONFIG_CMD_GPT=y
 # CONFIG_RANDOM_UUID is not set
 CONFIG_CMD_LOADM=y
 # CONFIG_CMD_LOADS is not set
-CONFIG_CMD_MMC=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_NFS is not set
@@ -45,8 +43,7 @@ CONFIG_OF_CONTROL=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_REGMAP=y
-CONFIG_FWU_MDATA=y
-CONFIG_FWU_MDATA_GPT_BLK=y
+CONFIG_ARM_FFA_TRANSPORT=y
 CONFIG_MISC=y
 # CONFIG_MMC is not set
 CONFIG_NVMXIP_QSPI=y
@@ -59,9 +56,15 @@ CONFIG_DM_RTC=y
 CONFIG_RTC_EMULATION=y
 CONFIG_DM_SERIAL=y
 CONFIG_SYSRESET=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
 CONFIG_USB=y
 CONFIG_USB_ISP1760=y
+CONFIG_ERRNO_STR=y
+CONFIG_EFI_MM_COMM_TEE=y
+CONFIG_FFA_SHARED_MM_BUF_SIZE=4096
+CONFIG_FFA_SHARED_MM_BUF_OFFSET=0
+CONFIG_FFA_SHARED_MM_BUF_ADDR=0x02000000
 CONFIG_EFI_CAPSULE_ON_DISK=y
 CONFIG_EFI_IGNORE_OSINDICATIONS=y
 CONFIG_FWU_MULTI_BANK_UPDATE=y
-CONFIG_ERRNO_STR=y
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH v19 8/9] arm_ffa: efi: introduce FF-A MM communication
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 8/9] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
@ 2023-08-04 18:35                                                                                                                                                                                       ` Tom Rini
  2023-08-07 14:47                                                                                                                                                                                       ` Ilias Apalodimas
  1 sibling, 0 replies; 478+ messages in thread
From: Tom Rini @ 2023-08-04 18:35 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, u-boot,
	Gowtham Suresh Kumar

[-- Attachment #1: Type: text/plain, Size: 2012 bytes --]

On Fri, Aug 04, 2023 at 02:33:44PM +0100, Abdellatif El Khlifi wrote:

> Add MM communication support using FF-A transport
> 
> This feature allows accessing MM partitions services through
> EFI MM communication protocol. MM partitions such as StandAlonneMM
> or smm-gateway secure partitions which reside in secure world.
> 
> An MM shared buffer and a door bell event are used to exchange
> the data.
> 
> The data is used by EFI services such as GetVariable()/SetVariable()
> and copied from the communication buffer to the MM shared buffer.
> 
> The secure partition is notified about availability of data in the
> MM shared buffer by an FF-A message (door bell).
> 
> On such event, MM SP can read the data and updates the MM shared
> buffer with the response data.
> 
> The response data is copied back to the communication buffer and
> consumed by the EFI subsystem.
> 
> MM communication protocol supports FF-A 64-bit direct messaging.
> 
> We tested the FF-A MM communication on the Corstone-1000 platform.
> 
> We ran the UEFI SCT test suite containing EFI setVariable, getVariable and
> getNextVariable tests which involve FF-A MM communication and all tests
> are passing with the current changes.
> 
> We made the SCT test reports (part of the ACS results) public following the
> latest Corstone-1000 platform software release. Please find the test
> reports at [1].
> 
> [1]: https://gitlab.arm.com/arm-reference-solutions/arm-reference-solutions-test-report/-/tree/master/embedded-a/corstone1000/CORSTONE1000-2023.06/acs_results_fpga.zip
> 
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Cc: Jens Wiklander <jens.wiklander@linaro.org>

Thanks for re-working things again.

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v19 0/9] introduce Arm FF-A support
  2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                       ` (8 preceding siblings ...)
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 9/9] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
@ 2023-08-04 18:35                                                                                                                                                                                     ` Tom Rini
  2023-08-07 15:30                                                                                                                                                                                       ` Abdellatif El Khlifi
  2023-08-08 19:25                                                                                                                                                                                     ` Tom Rini
  10 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-08-04 18:35 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, u-boot,
	Rob Herring, Drew Reed, Xueliang Zhong

[-- Attachment #1: Type: text/plain, Size: 2957 bytes --]

On Fri, Aug 04, 2023 at 02:33:36PM +0100, Abdellatif El Khlifi wrote:

> Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> 
> FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> communicate with each other. A partition could be a VM in the Normal or Secure world, an
> application in S-EL0, or a Trusted OS in S-EL1.
> 
> FF-A is a discoverable bus and similar to architecture features.
> FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> by the PSCI driver.
> 
>    => dm tree
> 
>     Class     Index  Probed  Driver                Name
>    -----------------------------------------------------------
>    ...
>     firmware      0  [ + ]   psci                      |-- psci
>     ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
>    ...
> 
> Clients are able to probe then use the FF-A bus by calling the DM class
> searching APIs (e.g: uclass_first_device).
> 
> This implementation of the specification provides support for Aarch64.
> 
> The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> 
>     - Discover the presence of secure partitions (SPs) of interest
>     - Access an SP's service through communication protocols
>       (e.g: EFI MM communication protocol)
> 
> The FF-A support provides the following features:
> 
>     - Being generic by design and can be used by any Arm 64-bit platform
>     - FF-A support can be compiled and used without EFI
>     - Support for SMCCCv1.2 x0-x17 registers
>     - Support for SMC32 calling convention
>     - Support for 32-bit and 64-bit FF-A direct messaging
>     - Support for FF-A MM communication (compatible with EFI boot time)
>     - Enabling FF-A and MM communication in Corstone1000 platform as a use case
>     - 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.
>     - Sandbox FF-A test cases.
>     - A new command called armffa is provided as an example of how to access the
>       FF-A bus
> 
> For more details about the FF-A support please refer to [B] and refer to [C] for
> how to use the armffa command.
> 
> Please find at [D] an example of the expected boot logs when enabling
> FF-A support for a platform. In this example the platform is
> Corstone1000. But it can be any Arm 64-bit platform.

Depending on further feedback, I will pick this up but likely just after
-rc2.  Given how long this has been going I will take it for v2023.10
all the same, thanks.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v19 8/9] arm_ffa: efi: introduce FF-A MM communication
  2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 8/9] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
  2023-08-04 18:35                                                                                                                                                                                       ` Tom Rini
@ 2023-08-07 14:47                                                                                                                                                                                       ` Ilias Apalodimas
  2023-08-07 15:26                                                                                                                                                                                         ` Abdellatif El Khlifi
  1 sibling, 1 reply; 478+ messages in thread
From: Ilias Apalodimas @ 2023-08-07 14:47 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: trini, achin.gupta, jens.wiklander, nd, sjg, u-boot,
	Gowtham Suresh Kumar

On Fri, Aug 04, 2023 at 02:33:44PM +0100, Abdellatif El Khlifi wrote:
> Add MM communication support using FF-A transport
> 
> This feature allows accessing MM partitions services through
> EFI MM communication protocol. MM partitions such as StandAlonneMM
> or smm-gateway secure partitions which reside in secure world.
> 
> An MM shared buffer and a door bell event are used to exchange
> the data.
> 
> The data is used by EFI services such as GetVariable()/SetVariable()
> and copied from the communication buffer to the MM shared buffer.
> 
> The secure partition is notified about availability of data in the
> MM shared buffer by an FF-A message (door bell).
> 
> On such event, MM SP can read the data and updates the MM shared
> buffer with the response data.
> 
> The response data is copied back to the communication buffer and
> consumed by the EFI subsystem.
> 
> MM communication protocol supports FF-A 64-bit direct messaging.
> 
> We tested the FF-A MM communication on the Corstone-1000 platform.
> 
> We ran the UEFI SCT test suite containing EFI setVariable, getVariable and
> getNextVariable tests which involve FF-A MM communication and all tests
> are passing with the current changes.
> 
> We made the SCT test reports (part of the ACS results) public following the
> latest Corstone-1000 platform software release. Please find the test
> reports at [1].
> 
> [1]: https://gitlab.arm.com/arm-reference-solutions/arm-reference-solutions-test-report/-/tree/master/embedded-a/corstone1000/CORSTONE1000-2023.06/acs_results_fpga.zip
> 
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Tested-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Cc: Jens Wiklander <jens.wiklander@linaro.org>
> 
> ---
> 
> Changelog:
> ===============
> 
> v19:
> 
> Tom:
> 
> * use CONFIG_FFA_SHARED_MM_BUF_* in place of macros
> 
> v18:
> 
> Ilias, Tom:
> 
> * drop the use of configs for the shared MM buffer, put back #ifdefs instead
> * add test information to the commit log
> 

Thanks for the quick rework.  I like the fact you have the SMC as a
fallback to FF-A in case it's not discovered.  Once and if we get dynamic 
buffer allocation for the NS-world we can easily switch this to an
automatically scanable feature again.

Tom, I am fine with the series now.  I've reviewed the relevant EFI and asm
bits, feel free to pull it in if the rest of the people are happy. 

Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>



> v17:
> 
> * show a debug message rather than an error when FF-A is not detected
> 
> v16:
> 
> * lib/efi_loader/Kconfig:
>    rather than automatically selecting OPTEE and ARM_FFA_TRANSPORT configs by
>    EFI_MM_COMM_TEE, set them as dependencies (Otherwise FF-A will be automatically
>    enabled for boards that don't need it).
> 
> v15:
> 
> Simon:
> 
> * replace FFA_SHARED_MM_BUFFER_* defines with configs
> 
> v14:
> 
> Ilias:
> 
> * drop truncating var_payload->size when using FF-A
> * map the MM SP return codes to errnos
> 
> v13:
> 
> * remove FF-A and Optee ifdefs
> 
> v12:
> 
> * drop use of calloc when querying SPs
> * address nits
> 
> v11:
> 
> * rename select_ffa_mm_comms() to select_mm_comms()
> * improve the logic of MM transport selection in mm_communicate()
> * addressing nits
> 
> v10:
> 
> * use the FF-A driver Uclass operations
> * use uclass_first_device()
> * addressing nits
> 
> v9: align how FF-A is used with FF-A discovery through DM
> 
> v8:
> 
> * isolate the compilation choices between FF-A and OP-TEE
> * update partition_info_get() second argument to be an SP count
> * pass NULL device pointer to the FF-A bus discovery and operations
> 
> v7:
> 
> * set the MM door bell event to use 64-bit direct messaging
> * issue a compile time error when one of these macros are not found :
>   FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR
> * make mm_sp_svc_uuid static
> * replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails
> * improve use of unmap_sysmem() in ffa_mm_communicate()
> 
> v6:
> 
> * add FF-A runtime discovery at MM communication level
> * drop EFI runtime support for FF-A MM communication
> * revert the changes in include/mm_communication.h for
>   efi_mm_communicate_header and smm_variable_access structures
> 
> v4:
> 
> * use the new FF-A driver interfaces
> * discover MM partitions at runtime
> * copy FF-A driver private data to EFI runtime section at
>   ExitBootServices()
> * drop use of FFA_ERR_STAT_SUCCESS error code
> * replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES
>   in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore
> * revert the error log in mm_communicate() in case of failure
> * remove packed attribute from efi_mm_communicate_header and
>   smm_variable_communicate_header
> 
> v2:
> 
> * set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings
> 
> v1:
> 
> * introduce FF-A MM communication
> 
> include/mm_communication.h        |  17 ++
>  lib/efi_loader/Kconfig            |  39 ++++-
>  lib/efi_loader/efi_variable_tee.c | 270 +++++++++++++++++++++++++++++-
>  3 files changed, 320 insertions(+), 6 deletions(-)
> 
> diff --git a/include/mm_communication.h b/include/mm_communication.h
> index e65fbde60d..f38f1a5344 100644
> --- a/include/mm_communication.h
> +++ b/include/mm_communication.h
> @@ -6,6 +6,9 @@
>   *  Copyright (c) 2017, Intel Corporation. All rights reserved.
>   *  Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org>
>   *  Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org>
> + *  Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
> + *    Authors:
> + *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
>   */
>  
>  #ifndef _MM_COMMUNICATION_H_
> @@ -13,6 +16,11 @@
>  
>  #include <part_efi.h>
>  
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
> +/* MM service UUID string (big-endian format). This UUID is  common across all MM SPs */
> +#define MM_SP_UUID	"33d532ed-e699-0942-c09c-a798d9cd722d"
> +#endif
> +
>  /*
>   * Interface to the pseudo Trusted Application (TA), which provides a
>   * communication channel with the Standalone MM (Management Mode)
> @@ -248,4 +256,13 @@ struct smm_variable_var_check_property {
>  	u16                       name[];
>  };
>  
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
> +/* supported MM transports */
> +enum mm_comms_select {
> +	MM_COMMS_UNDEFINED,
> +	MM_COMMS_FFA,
> +	MM_COMMS_OPTEE
> +};
> +#endif
> +
>  #endif /* _MM_COMMUNICATION_H_ */
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index c5835e6ef6..852f9671d8 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -55,13 +55,50 @@ config EFI_VARIABLE_FILE_STORE
>  	  stored as file /ubootefi.var on the EFI system partition.
>  
>  config EFI_MM_COMM_TEE
> -	bool "UEFI variables storage service via OP-TEE"
> +	bool "UEFI variables storage service via the trusted world"
>  	depends on OPTEE
>  	help
> +	  Allowing access to the MM SP services (SPs such as  StandAlonneMM, smm-gateway).
> +	  When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> +	  When using the u-boot FF-A  driver any MM SP is supported.
> +
>  	  If OP-TEE is present and running StandAloneMM, dispatch all UEFI
>  	  variable related operations to that. The application will verify,
>  	  authenticate and store the variables on an RPMB.
>  
> +	  When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related
> +	  operations to the MM SP running in the secure world.
> +	  A door bell mechanism is used to notify the SP when there is data in the shared
> +	  MM buffer. The data is copied by u-boot to the shared buffer before issuing
> +	  the door bell event.
> +
> +config FFA_SHARED_MM_BUF_SIZE
> +	int "Memory size of the shared MM communication buffer"
> +	depends on EFI_MM_COMM_TEE && ARM_FFA_TRANSPORT
> +	help
> +	  This defines the size in bytes of the memory area reserved for the shared
> +	  buffer used for communication between the MM feature in U-Boot and
> +	  the MM SP in secure world.
> +	  The size of the memory region must be a multiple of the size of the maximum
> +	  translation granule size that is specified in the ID_AA64MMFR0_EL1 System register.
> +	  It is assumed that the MM SP knows the size of the shared MM communication buffer.
> +
> +config FFA_SHARED_MM_BUF_OFFSET
> +	int "Data offset in the shared MM communication buffer"
> +	depends on EFI_MM_COMM_TEE && ARM_FFA_TRANSPORT
> +	help
> +	  This defines the offset in bytes of the data read or written to in the shared
> +	  buffer by the MM SP.
> +
> +config FFA_SHARED_MM_BUF_ADDR
> +	hex "Define the address of the shared MM communication buffer"
> +	depends on EFI_MM_COMM_TEE && ARM_FFA_TRANSPORT
> +	help
> +	  This defines the address of the shared MM communication buffer
> +	  used for communication between the MM feature in U-Boot and
> +	  the MM SP in secure world.
> +	  It is assumed that the MM SP knows the address of the shared MM communication buffer.
> +
>  config EFI_VARIABLE_NO_STORE
>  	bool "Don't persist non-volatile UEFI variables"
>  	help
> diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> index dfef18435d..09d03c0eee 100644
> --- a/lib/efi_loader/efi_variable_tee.c
> +++ b/lib/efi_loader/efi_variable_tee.c
> @@ -4,16 +4,38 @@
>   *
>   *  Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org>
>   *  Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org>
> + *  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>
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
> +#include <arm_ffa.h>
> +#endif
> +#include <cpu_func.h>
> +#include <dm.h>
>  #include <efi.h>
>  #include <efi_api.h>
>  #include <efi_loader.h>
>  #include <efi_variable.h>
> -#include <tee.h>
>  #include <malloc.h>
> +#include <mapmem.h>
>  #include <mm_communication.h>
> +#include <tee.h>
> +
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
> +/* MM return codes */
> +#define MM_SUCCESS (0)
> +#define MM_NOT_SUPPORTED (-1)
> +#define MM_INVALID_PARAMETER (-2)
> +#define MM_DENIED (-3)
> +#define MM_NO_MEMORY (-5)
> +
> +static const char *mm_sp_svc_uuid = MM_SP_UUID;
> +static u16 mm_sp_id;
> +#endif
>  
>  extern struct efi_var_file __efi_runtime_data *efi_var_buf;
>  static efi_uintn_t max_buffer_size;	/* comm + var + func + data */
> @@ -144,12 +166,238 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
>  	return ret;
>  }
>  
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
> +/**
> + * ffa_notify_mm_sp() - Announce there is data in the shared buffer
> + *
> + * Notify the MM partition in the trusted world that
> + * data is available in the shared buffer.
> + * This is a blocking call during which trusted world has exclusive access
> + * to the MM shared buffer.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_notify_mm_sp(void)
> +{
> +	struct ffa_send_direct_data msg = {0};
> +	int ret;
> +	int sp_event_ret;
> +	struct udevice *dev;
> +
> +	ret = uclass_first_device_err(UCLASS_FFA, &dev);
> +	if (ret) {
> +		log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
> +		return ret;
> +	}
> +
> +	msg.data0 = CONFIG_FFA_SHARED_MM_BUF_OFFSET; /* x3 */
> +
> +	ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
> +	if (ret)
> +		return ret;
> +
> +	sp_event_ret = msg.data0; /* x3 */
> +
> +	switch (sp_event_ret) {
> +	case MM_SUCCESS:
> +		ret = 0;
> +		break;
> +	case MM_NOT_SUPPORTED:
> +		ret = -EINVAL;
> +		break;
> +	case MM_INVALID_PARAMETER:
> +		ret = -EPERM;
> +		break;
> +	case MM_DENIED:
> +		ret = -EACCES;
> +		break;
> +	case MM_NO_MEMORY:
> +		ret = -EBUSY;
> +		break;
> +	default:
> +		ret = -EACCES;
> +	}
> +
> +	return ret;
> +}
> +
> +/**
> + * ffa_discover_mm_sp_id() - Query the MM partition ID
> + *
> + * Use the FF-A driver to get the MM partition ID.
> + * If multiple partitions are found, use the first one.
> + * This is a boot time function.
> + *
> + * Return:
> + *
> + * 0 on success
> + */
> +static int ffa_discover_mm_sp_id(void)
> +{
> +	u32 count = 0;
> +	int ret;
> +	struct ffa_partition_desc *descs;
> +	struct udevice *dev;
> +
> +	ret = uclass_first_device_err(UCLASS_FFA, &dev);
> +	if (ret) {
> +		log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n");
> +		return ret;
> +	}
> +
> +	/* Ask the driver to fill the buffer with the SPs info */
> +	ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, &descs);
> +	if (ret) {
> +		log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret);
> +		return ret;
> +	}
> +
> +	/* MM SPs found , use the first one */
> +
> +	mm_sp_id = descs[0].info.id;
> +
> +	log_info("EFI: MM partition ID 0x%x\n", mm_sp_id);
> +
> +	return 0;
> +}
> +
>  /**
> - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send
> + * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
> + * @comm_buf:		locally allocated communication buffer used for rx/tx
> + * @dsize:				communication buffer size
> + *
> + * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
> + * that there is data to read from the shared buffer.
> + * Communication with the MM SP is performed using FF-A transport.
> + * On the event, MM SP can read the data from the buffer and
> + * update the MM shared buffer with response data.
> + * The response data is copied back to the communication buffer.
> + *
> + * Return:
> + *
> + * EFI status code
> + */
> +static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
> +{
> +	ulong tx_data_size;
> +	int ffa_ret;
> +	efi_status_t efi_ret;
> +	struct efi_mm_communicate_header *mm_hdr;
> +	void *virt_shared_buf;
> +
> +	if (!comm_buf)
> +		return EFI_INVALID_PARAMETER;
> +
> +	/* Discover MM partition ID at boot time */
> +	if (!mm_sp_id && ffa_discover_mm_sp_id()) {
> +		log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
> +		return EFI_UNSUPPORTED;
> +	}
> +
> +	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> +	tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t);
> +
> +	if (comm_buf_size != tx_data_size || tx_data_size > CONFIG_FFA_SHARED_MM_BUF_SIZE)
> +		return EFI_INVALID_PARAMETER;
> +
> +	/* Copy the data to the shared buffer */
> +
> +	virt_shared_buf = map_sysmem((phys_addr_t)CONFIG_FFA_SHARED_MM_BUF_ADDR, 0);
> +	memcpy(virt_shared_buf, comm_buf, tx_data_size);
> +
> +	/*
> +	 * The secure world might have cache disabled for
> +	 * the device region used for shared buffer (which is the case for Optee).
> +	 * In this case, the secure world reads the data from DRAM.
> +	 * Let's flush the cache so the DRAM is updated with the latest data.
> +	 */
> +#ifdef CONFIG_ARM64
> +	invalidate_dcache_all();
> +#endif
> +
> +	/* Announce there is data in the shared buffer */
> +
> +	ffa_ret = ffa_notify_mm_sp();
> +
> +	switch (ffa_ret) {
> +	case 0: {
> +		ulong rx_data_size;
> +		/* Copy the MM SP response from the shared buffer to the communication buffer */
> +		rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len +
> +			sizeof(efi_guid_t) +
> +			sizeof(size_t);
> +
> +		if (rx_data_size > comm_buf_size) {
> +			efi_ret = EFI_OUT_OF_RESOURCES;
> +			break;
> +		}
> +
> +		memcpy(comm_buf, virt_shared_buf, rx_data_size);
> +		efi_ret = EFI_SUCCESS;
> +		break;
> +	}
> +	case -EINVAL:
> +		efi_ret = EFI_DEVICE_ERROR;
> +		break;
> +	case -EPERM:
> +		efi_ret = EFI_INVALID_PARAMETER;
> +		break;
> +	case -EACCES:
> +		efi_ret = EFI_ACCESS_DENIED;
> +		break;
> +	case -EBUSY:
> +		efi_ret = EFI_OUT_OF_RESOURCES;
> +		break;
> +	default:
> +		efi_ret = EFI_ACCESS_DENIED;
> +	}
> +
> +	unmap_sysmem(virt_shared_buf);
> +	return efi_ret;
> +}
> +
> +/**
> + * get_mm_comms() - detect the available MM transport
> + *
> + * Make sure the FF-A bus is probed successfully
> + * which means FF-A communication with secure world works and ready
> + * for use.
> + *
> + * If FF-A bus is not ready, use OPTEE comms.
> + *
> + * Return:
> + *
> + * MM_COMMS_FFA or MM_COMMS_OPTEE
> + */
> +static enum mm_comms_select get_mm_comms(void)
> +{
> +	struct udevice *dev;
> +	int ret;
> +
> +	ret = uclass_first_device_err(UCLASS_FFA, &dev);
> +	if (ret) {
> +		log_debug("EFI: Cannot find FF-A bus device, trying Optee comms\n");
> +		return MM_COMMS_OPTEE;
> +	}
> +
> +	return MM_COMMS_FFA;
> +}
> +#endif
> +
> +/**
> + * mm_communicate() - Adjust the communication buffer to the MM SP and send
>   * it to OP-TEE
>   *
> - * @comm_buf:		locally allocted communcation buffer
> + * @comm_buf:		locally allocated communication buffer
>   * @dsize:		buffer size
> + *
> + * The SP (also called partition) can be any MM SP such as  StandAlonneMM or smm-gateway.
> + * The comm_buf format is the same for both partitions.
> + * When using the u-boot OP-TEE driver, StandAlonneMM is supported.
> + * When using the u-boot FF-A  driver, any MM SP is supported.
> + *
>   * Return:		status code
>   */
>  static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
> @@ -157,12 +405,24 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize)
>  	efi_status_t ret;
>  	struct efi_mm_communicate_header *mm_hdr;
>  	struct smm_variable_communicate_header *var_hdr;
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
> +	enum mm_comms_select mm_comms;
> +#endif
>  
>  	dsize += MM_COMMUNICATE_HEADER_SIZE + MM_VARIABLE_COMMUNICATE_SIZE;
>  	mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
>  	var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
>  
> -	ret = optee_mm_communicate(comm_buf, dsize);
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
> +	mm_comms = get_mm_comms();
> +	if (mm_comms == MM_COMMS_FFA)
> +		ret = ffa_mm_communicate(comm_buf, dsize);
> +	else
> +		ret = optee_mm_communicate(comm_buf, dsize);
> +#else
> +		ret = optee_mm_communicate(comm_buf, dsize);
> +#endif
> +
>  	if (ret != EFI_SUCCESS) {
>  		log_err("%s failed!\n", __func__);
>  		return ret;
> @@ -697,7 +957,7 @@ void efi_variables_boot_exit_notify(void)
>  		ret = EFI_NOT_FOUND;
>  
>  	if (ret != EFI_SUCCESS)
> -		log_err("Unable to notify StMM for ExitBootServices\n");
> +		log_err("Unable to notify the MM partition for ExitBootServices\n");
>  	free(comm_buf);
>  
>  	/*
> -- 
> 2.25.1
> 

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v19 8/9] arm_ffa: efi: introduce FF-A MM communication
  2023-08-07 14:47                                                                                                                                                                                       ` Ilias Apalodimas
@ 2023-08-07 15:26                                                                                                                                                                                         ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-07 15:26 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: achin.gupta, nd, u-boot

Hi Ilias,

> > Add MM communication support using FF-A transport
> > 
> > This feature allows accessing MM partitions services through
> > EFI MM communication protocol. MM partitions such as StandAlonneMM
> > or smm-gateway secure partitions which reside in secure world.
> > ...
> > 
> > Changelog:
> > ===============
> > 
> > v19:
> > 
> > Tom:
> > 
> > * use CONFIG_FFA_SHARED_MM_BUF_* in place of macros
> > 
> > v18:
> > 
> > Ilias, Tom:
> > 
> > * drop the use of configs for the shared MM buffer, put back #ifdefs instead
> > * add test information to the commit log
> > 
> 
> Thanks for the quick rework.  I like the fact you have the SMC as a
> fallback to FF-A in case it's not discovered.  Once and if we get dynamic 
> buffer allocation for the NS-world we can easily switch this to an
> automatically scanable feature again.
> 
> Tom, I am fine with the series now.  I've reviewed the relevant EFI and asm
> bits, feel free to pull it in if the rest of the people are happy. 
> 
> Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> 

You're welcome :)

Cheers,
Abdellatif

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v19 0/9] introduce Arm FF-A support
  2023-08-04 18:35                                                                                                                                                                                     ` [PATCH v19 0/9] introduce Arm FF-A support Tom Rini
@ 2023-08-07 15:30                                                                                                                                                                                       ` Abdellatif El Khlifi
  0 siblings, 0 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-07 15:30 UTC (permalink / raw)
  To: Tom Rini; +Cc: nd, u-boot

Hi Tom,

> 
> > Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> > 
> > FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> > communicate with each other. A partition could be a VM in the Normal or Secure world, an
> > application in S-EL0, or a Trusted OS in S-EL1.
> > 
> > FF-A is a discoverable bus and similar to architecture features.
> > FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> > by the PSCI driver.
> >  ...
> > 
> Depending on further feedback, I will pick this up but likely just after
> -rc2.  Given how long this has been going I will take it for v2023.10
> all the same, thanks.
> 

Very much appreciated. Thank you :)

Cheers,
Abdellatif


^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v19 0/9] introduce Arm FF-A support
  2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
                                                                                                                                                                                                       ` (9 preceding siblings ...)
  2023-08-04 18:35                                                                                                                                                                                     ` [PATCH v19 0/9] introduce Arm FF-A support Tom Rini
@ 2023-08-08 19:25                                                                                                                                                                                     ` Tom Rini
  2023-08-09  2:03                                                                                                                                                                                       ` Simon Glass
  10 siblings, 1 reply; 478+ messages in thread
From: Tom Rini @ 2023-08-08 19:25 UTC (permalink / raw)
  To: Abdellatif El Khlifi
  Cc: achin.gupta, ilias.apalodimas, jens.wiklander, nd, sjg, u-boot,
	Rob Herring, Drew Reed, Xueliang Zhong

[-- Attachment #1: Type: text/plain, Size: 2840 bytes --]

On Fri, Aug 04, 2023 at 02:33:36PM +0100, Abdellatif El Khlifi wrote:

> Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> 
> FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> communicate with each other. A partition could be a VM in the Normal or Secure world, an
> application in S-EL0, or a Trusted OS in S-EL1.
> 
> FF-A is a discoverable bus and similar to architecture features.
> FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> by the PSCI driver.
> 
>    => dm tree
> 
>     Class     Index  Probed  Driver                Name
>    -----------------------------------------------------------
>    ...
>     firmware      0  [ + ]   psci                      |-- psci
>     ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
>    ...
> 
> Clients are able to probe then use the FF-A bus by calling the DM class
> searching APIs (e.g: uclass_first_device).
> 
> This implementation of the specification provides support for Aarch64.
> 
> The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> 
>     - Discover the presence of secure partitions (SPs) of interest
>     - Access an SP's service through communication protocols
>       (e.g: EFI MM communication protocol)
> 
> The FF-A support provides the following features:
> 
>     - Being generic by design and can be used by any Arm 64-bit platform
>     - FF-A support can be compiled and used without EFI
>     - Support for SMCCCv1.2 x0-x17 registers
>     - Support for SMC32 calling convention
>     - Support for 32-bit and 64-bit FF-A direct messaging
>     - Support for FF-A MM communication (compatible with EFI boot time)
>     - Enabling FF-A and MM communication in Corstone1000 platform as a use case
>     - 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.
>     - Sandbox FF-A test cases.
>     - A new command called armffa is provided as an example of how to access the
>       FF-A bus
> 
> For more details about the FF-A support please refer to [B] and refer to [C] for
> how to use the armffa command.
> 
> Please find at [D] an example of the expected boot logs when enabling
> FF-A support for a platform. In this example the platform is
> Corstone1000. But it can be any Arm 64-bit platform.

For the series, applied to u-boot/master, thanks!

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH v19 0/9] introduce Arm FF-A support
  2023-08-08 19:25                                                                                                                                                                                     ` Tom Rini
@ 2023-08-09  2:03                                                                                                                                                                                       ` Simon Glass
  2023-08-09 11:47                                                                                                                                                                                         ` [PATCH] arm_ffa: use debug logs Abdellatif El Khlifi
  0 siblings, 1 reply; 478+ messages in thread
From: Simon Glass @ 2023-08-09  2:03 UTC (permalink / raw)
  To: Tom Rini
  Cc: Abdellatif El Khlifi, achin.gupta, ilias.apalodimas,
	jens.wiklander, nd, u-boot, Rob Herring, Drew Reed,
	Xueliang Zhong

Hi,

On Tue, 8 Aug 2023 at 13:25, Tom Rini <trini@konsulko.com> wrote:
>
> On Fri, Aug 04, 2023 at 02:33:36PM +0100, Abdellatif El Khlifi wrote:
>
> > Adding support for Arm FF-A v1.0 (Arm Firmware Framework for Armv8-A) [A].
> >
> > FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
> > communicate with each other. A partition could be a VM in the Normal or Secure world, an
> > application in S-EL0, or a Trusted OS in S-EL1.
> >
> > FF-A is a discoverable bus and similar to architecture features.
> > FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
> > by the PSCI driver.
> >
> >    => dm tree
> >
> >     Class     Index  Probed  Driver                Name
> >    -----------------------------------------------------------
> >    ...
> >     firmware      0  [ + ]   psci                      |-- psci
> >     ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
> >    ...
> >
> > Clients are able to probe then use the FF-A bus by calling the DM class
> > searching APIs (e.g: uclass_first_device).
> >
> > This implementation of the specification provides support for Aarch64.
> >
> > The FF-A driver uses the SMC ABIs defined by the FF-A specification to:
> >
> >     - Discover the presence of secure partitions (SPs) of interest
> >     - Access an SP's service through communication protocols
> >       (e.g: EFI MM communication protocol)
> >
> > The FF-A support provides the following features:
> >
> >     - Being generic by design and can be used by any Arm 64-bit platform
> >     - FF-A support can be compiled and used without EFI
> >     - Support for SMCCCv1.2 x0-x17 registers
> >     - Support for SMC32 calling convention
> >     - Support for 32-bit and 64-bit FF-A direct messaging
> >     - Support for FF-A MM communication (compatible with EFI boot time)
> >     - Enabling FF-A and MM communication in Corstone1000 platform as a use case
> >     - 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.
> >     - Sandbox FF-A test cases.
> >     - A new command called armffa is provided as an example of how to access the
> >       FF-A bus
> >
> > For more details about the FF-A support please refer to [B] and refer to [C] for
> > how to use the armffa command.
> >
> > Please find at [D] an example of the expected boot logs when enabling
> > FF-A support for a platform. In this example the platform is
> > Corstone1000. But it can be any Arm 64-bit platform.
>
> For the series, applied to u-boot/master, thanks!

Oh dear. Running this I see this debug output. Please can you suppress it?

Emulated FF-A framework discovery
FF-A emulator ready to use
FF-A driver 1.0
FF-A framework 1.0
FF-A versions are compatible
Test: dm_test_power_regulator_autoset_list: regulator.c (flat tree)
Emulated FF-A framework discovery
FF-A emulator ready to use
FF-A driver 1.0
FF-A framework 1.0
FF-A versions are compatible
Emulated FF-A framework discovery
FF-A emulator ready to use
FF-A driver 1.0
FF-A framework 1.0
FF-A versions are compatible

Regards,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* [PATCH] arm_ffa: use debug logs
  2023-08-09  2:03                                                                                                                                                                                       ` Simon Glass
@ 2023-08-09 11:47                                                                                                                                                                                         ` Abdellatif El Khlifi
  2023-08-10  1:15                                                                                                                                                                                           ` Simon Glass
  2023-08-17 19:02                                                                                                                                                                                           ` Tom Rini
  0 siblings, 2 replies; 478+ messages in thread
From: Abdellatif El Khlifi @ 2023-08-09 11:47 UTC (permalink / raw)
  To: sjg; +Cc: Drew.Reed, Xueliang.Zhong, abdellatif.elkhlifi, nd, trini, u-boot

replace info logs with debug logs

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Cc: Tom Rini <trini@konsulko.com>
Cc: Simon Glass <sjg@chromium.org>
---
 doc/arch/arm64.ffa.rst                     | 2 +-
 drivers/firmware/arm-ffa/arm-ffa-uclass.c  | 4 ++--
 drivers/firmware/arm-ffa/arm-ffa.c         | 2 +-
 drivers/firmware/arm-ffa/ffa-emul-uclass.c | 2 +-
 drivers/firmware/arm-ffa/sandbox_ffa.c     | 2 +-
 5 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 325fb80346..4ecdc31716 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -231,7 +231,7 @@ Please refer the command documentation at :doc:`../usage/cmd/armffa`
 Example of boot logs with FF-A enabled
 --------------------------------------
 
-For example, when using FF-A with Corstone-1000 the logs are as follows:
+For example, when using FF-A with Corstone-1000, debug logs enabled, the output is as follows:
 
 ::
 
diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
index ffa9d81fa7..8c17b19eaf 100644
--- a/drivers/firmware/arm-ffa/arm-ffa-uclass.c
+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c
@@ -201,11 +201,11 @@ int ffa_get_version_hdlr(struct udevice *dev)
 	major = GET_FFA_MAJOR_VERSION(res.a0);
 	minor = GET_FFA_MINOR_VERSION(res.a0);
 
-	log_info("FF-A driver %d.%d\nFF-A framework %d.%d\n",
+	log_debug("FF-A driver %d.%d\nFF-A framework %d.%d\n",
 		 FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
 
 	if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) {
-		log_info("FF-A versions are compatible\n");
+		log_debug("FF-A versions are compatible\n");
 
 		if (dev) {
 			uc_priv = dev_get_uclass_priv(dev);
diff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c
index 68df75bd9e..ee0bf9a55b 100644
--- a/drivers/firmware/arm-ffa/arm-ffa.c
+++ b/drivers/firmware/arm-ffa/arm-ffa.c
@@ -42,7 +42,7 @@ static bool arm_ffa_discover(struct udevice *dev)
 {
 	int ret;
 
-	log_info("Arm FF-A framework discovery\n");
+	log_debug("Arm FF-A framework discovery\n");
 
 	ret = ffa_get_version_hdlr(dev);
 	if (ret)
diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
index 5562bbaac3..4bf9f6041f 100644
--- a/drivers/firmware/arm-ffa/ffa-emul-uclass.c
+++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
@@ -695,7 +695,7 @@ int ffa_emul_find(struct udevice *dev, struct udevice **emulp)
 		return ret;
 	}
 
-	log_info("FF-A emulator ready to use\n");
+	log_debug("FF-A emulator ready to use\n");
 
 	return 0;
 }
diff --git a/drivers/firmware/arm-ffa/sandbox_ffa.c b/drivers/firmware/arm-ffa/sandbox_ffa.c
index ef9491ccea..11142429c0 100644
--- a/drivers/firmware/arm-ffa/sandbox_ffa.c
+++ b/drivers/firmware/arm-ffa/sandbox_ffa.c
@@ -30,7 +30,7 @@ static int sandbox_ffa_discover(struct udevice *dev)
 	int ret;
 	struct udevice *emul;
 
-	log_info("Emulated FF-A framework discovery\n");
+	log_debug("Emulated FF-A framework discovery\n");
 
 	ret = ffa_emul_find(dev, &emul);
 	if (ret) {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 478+ messages in thread

* Re: [PATCH] arm_ffa: use debug logs
  2023-08-09 11:47                                                                                                                                                                                         ` [PATCH] arm_ffa: use debug logs Abdellatif El Khlifi
@ 2023-08-10  1:15                                                                                                                                                                                           ` Simon Glass
  2023-08-17 19:02                                                                                                                                                                                           ` Tom Rini
  1 sibling, 0 replies; 478+ messages in thread
From: Simon Glass @ 2023-08-10  1:15 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: Drew.Reed, Xueliang.Zhong, nd, trini, u-boot

On Wed, 9 Aug 2023 at 05:47, Abdellatif El Khlifi
<abdellatif.elkhlifi@arm.com> wrote:
>
> replace info logs with debug logs
>
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Simon Glass <sjg@chromium.org>
> ---
>  doc/arch/arm64.ffa.rst                     | 2 +-
>  drivers/firmware/arm-ffa/arm-ffa-uclass.c  | 4 ++--
>  drivers/firmware/arm-ffa/arm-ffa.c         | 2 +-
>  drivers/firmware/arm-ffa/ffa-emul-uclass.c | 2 +-
>  drivers/firmware/arm-ffa/sandbox_ffa.c     | 2 +-
>  5 files changed, 6 insertions(+), 6 deletions(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

Thanks,
Simon

^ permalink raw reply	[flat|nested] 478+ messages in thread

* Re: [PATCH] arm_ffa: use debug logs
  2023-08-09 11:47                                                                                                                                                                                         ` [PATCH] arm_ffa: use debug logs Abdellatif El Khlifi
  2023-08-10  1:15                                                                                                                                                                                           ` Simon Glass
@ 2023-08-17 19:02                                                                                                                                                                                           ` Tom Rini
  1 sibling, 0 replies; 478+ messages in thread
From: Tom Rini @ 2023-08-17 19:02 UTC (permalink / raw)
  To: Abdellatif El Khlifi; +Cc: sjg, Drew.Reed, Xueliang.Zhong, nd, u-boot

[-- Attachment #1: Type: text/plain, Size: 354 bytes --]

On Wed, Aug 09, 2023 at 12:47:30PM +0100, Abdellatif El Khlifi wrote:

> replace info logs with debug logs
> 
> Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Simon Glass <sjg@chromium.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 478+ messages in thread

end of thread, other threads:[~2023-08-17 19:03 UTC | newest]

Thread overview: 478+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-29 15:16 [PATCH 0/6] introduce Arm FF-A support abdellatif.elkhlifi
2022-03-29 15:16 ` [PATCH 1/6] arm_ffa: introduce Arm FF-A low-level driver abdellatif.elkhlifi
2022-03-29 15:16 ` [PATCH 2/6] arm_ffa: introduce armffa command abdellatif.elkhlifi
2023-07-27  5:51   ` Heinrich Schuchardt
2023-07-27  9:00     ` Abdellatif El Khlifi
2023-07-28  1:52       ` Simon Glass
2023-07-28  9:53         ` Abdellatif El Khlifi
2022-03-29 15:16 ` [PATCH 3/6] arm_ffa: introduce the FF-A Sandbox driver abdellatif.elkhlifi
2022-03-29 15:16 ` [PATCH 4/6] arm_ffa: introduce Sandbox test cases for UCLASS_FFA abdellatif.elkhlifi
2022-03-29 15:16 ` [PATCH 5/6] arm_ffa: introduce armffa command Sandbox test abdellatif.elkhlifi
2022-03-29 15:16 ` [PATCH 6/6] arm_ffa: introduce FF-A MM communication abdellatif.elkhlifi
2022-04-14 19:54   ` Ilias Apalodimas
2022-09-26 10:56     ` Abdellatif El Khlifi
2022-04-06 15:51 ` [PATCH 0/6] introduce Arm FF-A support Abdellatif El Khlifi
2022-04-06 19:47 ` Tom Rini
2022-04-07 12:54   ` Abdellatif El Khlifi
2022-04-07 12:58     ` Tom Rini
2022-04-12 11:43       ` Abdellatif El Khlifi
2022-04-12 12:01         ` Tom Rini
2022-04-12 13:28           ` Rob Herring
2022-04-13 14:20             ` Abdellatif El Khlifi
2022-04-13 16:46               ` Tom Rini
2022-04-13 17:29                 ` Sudeep Holla
2022-04-15 12:27                   ` [PATCH v2 " abdellatif.elkhlifi
2022-04-15 12:27                     ` [PATCH v2 1/6] arm_ffa: introduce Arm FF-A low-level driver abdellatif.elkhlifi
2022-05-13 14:23                       ` Ilias Apalodimas
2022-09-26 10:42                         ` Abdellatif El Khlifi
2022-05-13 14:40                       ` Jens Wiklander
2022-09-26 11:30                         ` Abdellatif El Khlifi
2022-04-15 12:27                     ` [PATCH v2 2/6] arm_ffa: introduce armffa command abdellatif.elkhlifi
2022-04-15 12:28                     ` [PATCH v2 3/6] arm_ffa: introduce the FF-A Sandbox driver abdellatif.elkhlifi
2022-04-15 12:28                     ` [PATCH v2 4/6] arm_ffa: introduce Sandbox test cases for UCLASS_FFA abdellatif.elkhlifi
2022-04-15 12:28                     ` [PATCH v2 5/6] arm_ffa: introduce armffa command Sandbox test abdellatif.elkhlifi
2022-04-15 12:28                     ` [PATCH v2 6/6] arm_ffa: introduce FF-A MM communication abdellatif.elkhlifi
2022-04-15 15:43                     ` [PATCH v2 0/6] introduce Arm FF-A support Tom Rini
2022-05-09 10:55                       ` Abdellatif El Khlifi
2022-05-12 14:04                         ` Abdellatif El Khlifi
2022-05-12 14:43                           ` Ilias Apalodimas
2022-08-01 17:20                             ` [PATCH v3 0/4] " Abdellatif El Khlifi
2022-08-01 17:20                               ` [PATCH v3 1/4] arm64: smccc: add Xn registers support used by SMC calls Abdellatif El Khlifi
2022-08-01 18:41                                 ` Sudeep Holla
2022-08-05 11:17                                   ` Abdellatif El Khlifi
2022-08-01 17:20                               ` [PATCH v3 2/4] arm64: smccc: clear the Xn registers after " Abdellatif El Khlifi
2022-08-16 11:48                                 ` Jens Wiklander
2022-09-26 11:33                                   ` Abdellatif El Khlifi
2022-08-01 17:20                               ` [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
2022-08-12  7:39                                 ` Ilias Apalodimas
2022-09-26 11:11                                   ` Abdellatif El Khlifi
2022-08-13  2:21                                 ` Simon Glass
2022-09-26 11:37                                   ` Abdellatif El Khlifi
2022-11-15 15:24                                 ` Simon Glass
2022-11-16 13:03                                   ` Abdellatif El Khlifi
2022-11-18 20:50                                     ` Simon Glass
2022-11-22 13:49                                       ` Abdellatif El Khlifi
2022-11-22 22:24                                         ` Simon Glass
2022-08-01 17:20                               ` [PATCH v3 4/4] arm_ffa: introduce armffa command Abdellatif El Khlifi
2022-09-26 10:17                               ` [PATCH v4 00/10] introduce Arm FF-A support Abdellatif El Khlifi
2022-09-26 10:17                                 ` [PATCH v4 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2022-09-26 10:17                                 ` [PATCH v4 02/10] arm64: smccc: clear the Xn registers after SMC calls Abdellatif El Khlifi
2022-09-26 10:17                                 ` [PATCH v4 03/10] lib: uuid: introduce be_uuid_str_to_le_bin function Abdellatif El Khlifi
2022-09-26 10:17                                 ` [PATCH v4 04/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
2022-09-26 10:17                                 ` [PATCH v4 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
2022-09-26 10:17                                 ` [PATCH v4 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
2022-09-26 10:17                                 ` [PATCH v4 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2022-09-26 10:17                                 ` [PATCH v4 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2022-09-26 10:17                                 ` [PATCH v4 09/10] arm_ffa: introduce FF-A MM communication Abdellatif El Khlifi
2022-09-26 10:17                                 ` [PATCH v4 10/10] arm_ffa: corstone1000: enable EFI " Abdellatif El Khlifi
2022-09-26 14:08                                 ` [PATCH v5 00/10] introduce Arm FF-A support Abdellatif El Khlifi
2022-09-26 14:08                                   ` [PATCH v5 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2022-09-26 14:08                                   ` [PATCH v5 02/10] arm64: smccc: clear the Xn registers after SMC calls Abdellatif El Khlifi
2022-09-30  9:48                                     ` Jens Wiklander
2022-10-14 10:17                                       ` Abdellatif El Khlifi
2022-09-26 14:08                                   ` [PATCH v5 03/10] lib: uuid: introduce be_uuid_str_to_le_bin function Abdellatif El Khlifi
2022-09-26 14:08                                   ` [PATCH v5 04/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
2022-10-03  8:49                                     ` Jens Wiklander
2022-10-03 15:22                                       ` Tom Rini
2022-10-14 10:40                                         ` Abdellatif El Khlifi
2022-10-14 10:28                                       ` Abdellatif El Khlifi
2022-09-26 14:08                                   ` [PATCH v5 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
2022-09-26 14:08                                   ` [PATCH v5 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
2022-09-26 14:08                                   ` [PATCH v5 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2022-09-26 14:08                                   ` [PATCH v5 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2022-09-26 14:08                                   ` [PATCH v5 09/10] arm_ffa: introduce FF-A MM communication Abdellatif El Khlifi
2022-09-29  9:32                                     ` Ilias Apalodimas
2022-10-14 10:38                                       ` Abdellatif El Khlifi
2022-10-14 15:55                                         ` Simon Glass
2022-10-14 16:08                                           ` Ilias Apalodimas
2022-10-17 14:15                                           ` Abdellatif El Khlifi
2022-09-26 14:08                                   ` [PATCH v5 10/10] arm_ffa: corstone1000: enable EFI " Abdellatif El Khlifi
2022-10-13 10:38                                   ` [PATCH v6 00/10] introduce Arm FF-A support Abdellatif El Khlifi
2022-10-13 10:38                                     ` [PATCH v6 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2022-10-24 14:19                                       ` Jens Wiklander
2022-11-08 11:13                                         ` Abdellatif El Khlifi
2022-10-13 10:38                                     ` [PATCH v6 02/10] lib: uuid: introduce be_uuid_str_to_le_bin function Abdellatif El Khlifi
2022-10-24 12:07                                       ` Ilias Apalodimas
2022-11-08 10:45                                         ` Abdellatif El Khlifi
2022-10-13 10:38                                     ` [PATCH v6 03/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
2022-10-25  9:31                                       ` Jens Wiklander
2022-10-25 10:27                                         ` Abdellatif El Khlifi
2022-11-08 11:28                                         ` Abdellatif El Khlifi
2022-10-13 10:38                                     ` [PATCH v6 04/10] arm_ffa: efi: unmap RX/TX buffers Abdellatif El Khlifi
2022-10-24 12:08                                       ` Ilias Apalodimas
2022-11-08 10:48                                         ` Abdellatif El Khlifi
2022-10-13 10:38                                     ` [PATCH v6 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
2022-10-13 10:38                                     ` [PATCH v6 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
2022-10-13 10:38                                     ` [PATCH v6 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2022-10-24 12:10                                       ` Ilias Apalodimas
2022-11-08 10:53                                         ` Abdellatif El Khlifi
2022-10-13 10:38                                     ` [PATCH v6 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2022-10-13 10:38                                     ` [PATCH v6 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2022-10-24 12:30                                       ` Ilias Apalodimas
2022-11-08 10:58                                         ` Abdellatif El Khlifi
2022-10-13 10:38                                     ` [PATCH v6 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2022-10-24 12:13                                       ` Ilias Apalodimas
2022-11-08 11:01                                         ` Abdellatif El Khlifi
2022-10-13 12:07                                     ` [PATCH v6 00/10] introduce Arm FF-A support Ilias Apalodimas
2022-10-14 10:44                                       ` Abdellatif El Khlifi
2022-11-07 19:20                                     ` [PATCH v7 " Abdellatif El Khlifi
2022-11-07 19:20                                       ` [PATCH v7 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2022-11-07 19:20                                       ` [PATCH v7 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
2022-11-08 13:47                                         ` Ilias Apalodimas
2022-11-11 12:32                                           ` Abdellatif El Khlifi
2022-11-11 12:36                                             ` Ilias Apalodimas
2022-11-11 17:02                                         ` Anders Dellien
2022-11-14 10:11                                           ` Abdellatif El Khlifi
2022-11-07 19:20                                       ` [PATCH v7 03/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
2022-11-09 11:51                                         ` Jens Wiklander
2022-11-11 14:36                                           ` Abdellatif El Khlifi
2022-11-15 10:32                                             ` Jens Wiklander
2022-11-22 13:33                                               ` Abdellatif El Khlifi
2022-11-22 13:28                                           ` Abdellatif El Khlifi
2022-11-07 19:20                                       ` [PATCH v7 04/10] arm_ffa: efi: unmap RX/TX buffers Abdellatif El Khlifi
2022-11-07 19:20                                       ` [PATCH v7 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
2022-11-07 19:20                                       ` [PATCH v7 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
2022-11-07 19:20                                       ` [PATCH v7 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2022-11-07 19:20                                       ` [PATCH v7 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2022-11-07 19:20                                       ` [PATCH v7 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2022-11-15  9:03                                         ` Ilias Apalodimas
2022-11-22 13:37                                           ` Abdellatif El Khlifi
2022-11-07 19:20                                       ` [PATCH v7 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2022-11-11 14:42                                       ` [PATCH v7 00/10] introduce Arm FF-A support Abdellatif El Khlifi
2022-11-22 13:17                                       ` [PATCH v8 " Abdellatif El Khlifi
2022-11-22 13:17                                         ` [PATCH v8 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2022-11-22 13:17                                         ` [PATCH v8 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
2022-11-23  2:09                                           ` Simon Glass
2022-11-22 13:17                                         ` [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
2022-11-23  2:09                                           ` Simon Glass
2022-11-24 13:21                                             ` Abdellatif El Khlifi
2022-11-25 21:17                                               ` Simon Glass
2022-11-28 16:22                                                 ` Rob Herring
2022-11-28 16:26                                                   ` Ilias Apalodimas
2022-12-04 19:22                                                   ` Simon Glass
2022-12-05 15:49                                                     ` Rob Herring
2022-12-19 11:12                                                       ` Abdellatif El Khlifi
2022-12-19 19:20                                                         ` Simon Glass
2023-01-12  2:10                                                           ` Rob Herring
2023-01-12 23:43                                                             ` Simon Glass
2023-01-13 10:44                                                               ` Abdellatif El Khlifi
2023-01-13 18:00                                                                 ` Simon Glass
2023-01-16 13:23                                                                   ` Abdellatif El Khlifi
2023-01-17 14:04                                                                     ` Tom Rini
2023-01-18  3:18                                                                       ` Rob Herring
2023-01-18  2:51                                                               ` Rob Herring
2023-01-18 12:49                                                                 ` Tom Rini
2023-01-18 13:46                                                                   ` Sudeep Holla
2023-01-18 13:59                                                                     ` Tom Rini
2023-01-18 15:49                                                                       ` Sudeep Holla
2023-01-19 16:31                                                                       ` Abdellatif El Khlifi
2023-01-19 16:40                                                                         ` Tom Rini
2023-01-19 16:41                                                                         ` Simon Glass
2023-01-19 16:43                                                                           ` Tom Rini
2023-01-19 16:56                                                                           ` Sudeep Holla
2023-01-20  9:56                                                                             ` Abdellatif El Khlifi
2023-01-19 18:11                                                                           ` Rob Herring
2023-01-20 10:33                                                                             ` Sudeep Holla
2023-01-20 22:04                                                                             ` Simon Glass
2023-01-23 15:13                                                                               ` Rob Herring
2023-01-23 16:32                                                                                 ` Simon Glass
2023-01-24 15:56                                                                                   ` Abdellatif El Khlifi
2023-01-24 22:44                                                                                     ` Simon Glass
2023-01-25  7:48                                                                                     ` Sudeep Holla
2023-01-25 10:55                                                                                       ` Abdellatif El Khlifi
2023-01-25 12:54                                                                                         ` Sudeep Holla
2023-01-25 16:00                                                                                     ` Rob Herring
2023-01-25 16:44                                                                                       ` Abdellatif El Khlifi
2023-01-25 17:11                                                                                         ` Sudeep Holla
2023-03-10 14:10                                                                                   ` [PATCH v9 00/10] introduce Arm FF-A support Abdellatif El Khlifi
2023-03-10 14:10                                                                                     ` [PATCH v9 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2023-03-10 14:10                                                                                     ` [PATCH v9 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
2023-03-10 20:49                                                                                       ` Simon Glass
2023-03-10 14:10                                                                                     ` [PATCH v9 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
2023-03-10 14:10                                                                                     ` [PATCH v9 04/10] arm_ffa: introduce Arm FF-A low-level driver Abdellatif El Khlifi
2023-03-10 14:10                                                                                     ` [PATCH v9 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
2023-03-10 20:49                                                                                       ` Simon Glass
2023-03-10 14:10                                                                                     ` [PATCH v9 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
2023-03-10 20:49                                                                                       ` Simon Glass
2023-03-14 12:55                                                                                         ` Abdellatif El Khlifi
2023-03-14 17:59                                                                                         ` Abdellatif El Khlifi
2023-03-15 14:05                                                                                           ` Simon Glass
2023-03-10 14:10                                                                                     ` [PATCH v9 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2023-03-10 20:49                                                                                       ` Simon Glass
2023-03-10 14:10                                                                                     ` [PATCH v9 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2023-03-10 20:50                                                                                       ` Simon Glass
2023-03-10 14:10                                                                                     ` [PATCH v9 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2023-03-10 20:50                                                                                       ` Simon Glass
2023-03-14 17:05                                                                                         ` Abdellatif El Khlifi
2023-03-10 14:10                                                                                     ` [PATCH v9 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2023-03-10 20:50                                                                                     ` [PATCH v9 00/10] introduce Arm FF-A support Simon Glass
2023-03-28 16:11                                                                                       ` [PATCH v10 " Abdellatif El Khlifi
2023-03-28 16:11                                                                                         ` [PATCH v10 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2023-03-29 20:02                                                                                           ` Simon Glass
2023-03-28 16:11                                                                                         ` [PATCH v10 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
2023-03-28 16:11                                                                                         ` [PATCH v10 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
2023-03-29 20:02                                                                                           ` Simon Glass
2023-03-30 10:27                                                                                             ` Abdellatif El Khlifi
2023-03-28 16:11                                                                                         ` [PATCH v10 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
2023-04-02  2:41                                                                                           ` Simon Glass
2023-03-28 16:11                                                                                         ` [PATCH v10 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
2023-04-02  2:40                                                                                           ` Simon Glass
2023-04-12  9:48                                                                                             ` Abdellatif El Khlifi
2023-03-28 16:11                                                                                         ` [PATCH v10 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
2023-04-02  2:41                                                                                           ` Simon Glass
2023-04-12  9:52                                                                                             ` Abdellatif El Khlifi
2023-03-28 16:11                                                                                         ` [PATCH v10 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2023-04-02  2:40                                                                                           ` Simon Glass
2023-03-28 16:11                                                                                         ` [PATCH v10 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2023-03-28 16:11                                                                                         ` [PATCH v10 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2023-03-31  8:29                                                                                           ` Ilias Apalodimas
2023-04-12  9:59                                                                                             ` Abdellatif El Khlifi
2023-03-28 16:11                                                                                         ` [PATCH v10 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2023-04-02  2:41                                                                                           ` Simon Glass
2023-04-03  9:59                                                                                             ` Ilias Apalodimas
2023-04-03 10:33                                                                                               ` Abdellatif El Khlifi
2023-04-12  9:42                                                                                         ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
2023-04-12  9:42                                                                                           ` [PATCH v11 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2023-04-12  9:42                                                                                           ` [PATCH v11 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
2023-04-12  9:42                                                                                           ` [PATCH v11 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
2023-04-19  1:46                                                                                             ` Simon Glass
2023-04-12  9:42                                                                                           ` [PATCH v11 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
2023-04-19  1:49                                                                                             ` Simon Glass
2023-04-12  9:42                                                                                           ` [PATCH v11 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
2023-04-12 14:02                                                                                             ` Heinrich Schuchardt
2023-04-12 15:53                                                                                               ` Abdellatif El Khlifi
2023-04-12 20:00                                                                                                 ` Heinrich Schuchardt
2023-04-13 10:15                                                                                                   ` Abdellatif El Khlifi
2023-04-19  1:49                                                                                             ` Simon Glass
2023-05-12 12:14                                                                                               ` Abdellatif El Khlifi
2023-04-12  9:42                                                                                           ` [PATCH v11 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
2023-04-19  1:49                                                                                             ` Simon Glass
2023-05-03 17:56                                                                                               ` Abdellatif El Khlifi
2023-04-12  9:42                                                                                           ` [PATCH v11 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2023-04-19  1:50                                                                                             ` Simon Glass
2023-04-12  9:42                                                                                           ` [PATCH v11 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2023-04-19  1:50                                                                                             ` Simon Glass
2023-04-12  9:42                                                                                           ` [PATCH v11 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2023-04-19  1:49                                                                                             ` Simon Glass
2023-05-12 12:12                                                                                               ` Abdellatif El Khlifi
2023-04-21  8:10                                                                                             ` Ilias Apalodimas
2023-04-12  9:42                                                                                           ` [PATCH v11 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2023-04-17 16:02                                                                                           ` [PATCH v11 00/10] introduce Arm FF-A support Abdellatif El Khlifi
2023-04-18 16:48                                                                                             ` Simon Glass
2023-05-12 12:10                                                                                           ` [PATCH v12 " Abdellatif El Khlifi
2023-05-12 12:10                                                                                             ` [PATCH v12 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2023-05-19 12:56                                                                                               ` Ilias Apalodimas
2023-05-12 12:10                                                                                             ` [PATCH v12 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
2023-05-12 12:10                                                                                             ` [PATCH v12 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
2023-05-12 12:10                                                                                             ` [PATCH v12 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
2023-05-12 12:10                                                                                             ` [PATCH v12 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
2023-05-12 12:10                                                                                             ` [PATCH v12 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
2023-05-12 12:10                                                                                             ` [PATCH v12 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2023-05-12 12:10                                                                                             ` [PATCH v12 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2023-05-12 12:10                                                                                             ` [PATCH v12 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2023-05-19 12:56                                                                                               ` Ilias Apalodimas
2023-05-19 13:36                                                                                                 ` Abdellatif El Khlifi
2023-05-19 14:07                                                                                                   ` Ilias Apalodimas
2023-05-12 12:10                                                                                             ` [PATCH v12 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2023-05-22  9:13                                                                                             ` [PATCH v12 00/10] introduce Arm FF-A support Abdellatif El Khlifi
2023-06-06 11:56                                                                                               ` Abdellatif El Khlifi
2023-06-06 13:48                                                                                                 ` Tom Rini
2023-06-16 15:28                                                                                                   ` [PATCH v13 " Abdellatif El Khlifi
2023-06-16 15:28                                                                                                     ` [PATCH v13 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2023-06-20 14:05                                                                                                       ` Ilias Apalodimas
2023-07-03  9:47                                                                                                         ` Abdellatif El Khlifi
2023-06-16 15:28                                                                                                     ` [PATCH v13 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
2023-06-16 15:28                                                                                                     ` [PATCH v13 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
2023-06-20 10:27                                                                                                       ` Simon Glass
2023-06-16 15:28                                                                                                     ` [PATCH v13 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
2023-06-20 10:27                                                                                                       ` Simon Glass
2023-06-30 12:49                                                                                                         ` Abdellatif El Khlifi
2023-07-02 15:44                                                                                                           ` Simon Glass
2023-07-03  9:41                                                                                                             ` Abdellatif El Khlifi
2023-06-16 15:28                                                                                                     ` [PATCH v13 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
2023-06-20 10:27                                                                                                       ` Simon Glass
2023-06-20 14:25                                                                                                       ` Ilias Apalodimas
2023-07-03  9:55                                                                                                         ` Abdellatif El Khlifi
2023-07-03  9:59                                                                                                           ` Ilias Apalodimas
2023-07-03 12:08                                                                                                             ` Abdellatif El Khlifi
2023-07-03 13:30                                                                                                               ` Simon Glass
2023-07-03 15:53                                                                                                                 ` Abdellatif El Khlifi
2023-07-04  2:40                                                                                                                   ` Simon Glass
2023-07-07 14:43                                                                                                                     ` [PATCH v14 00/11] introduce Arm FF-A support Abdellatif El Khlifi
2023-07-07 14:44                                                                                                                       ` [PATCH v14 01/11] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2023-07-07 14:44                                                                                                                       ` [PATCH v14 02/11] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
2023-07-07 14:44                                                                                                                       ` [PATCH v14 03/11] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
2023-07-07 14:44                                                                                                                       ` [PATCH v14 04/11] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
2023-07-07 14:44                                                                                                                       ` [PATCH v14 05/11] log: select physical address formatting in a generic way Abdellatif El Khlifi
2023-07-07 17:34                                                                                                                         ` Simon Glass
2023-07-10 12:14                                                                                                                           ` Abdellatif El Khlifi
2023-07-10 14:17                                                                                                                             ` Simon Glass
2023-07-10 14:49                                                                                                                               ` Abdellatif El Khlifi
2023-07-10 19:45                                                                                                                                 ` Simon Glass
2023-07-07 14:44                                                                                                                       ` [PATCH v14 06/11] arm_ffa: introduce armffa command Abdellatif El Khlifi
2023-07-07 14:44                                                                                                                       ` [PATCH v14 07/11] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
2023-07-07 17:35                                                                                                                         ` Simon Glass
2023-07-07 14:44                                                                                                                       ` [PATCH v14 08/11] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2023-07-07 14:44                                                                                                                       ` [PATCH v14 09/11] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2023-07-07 14:44                                                                                                                       ` [PATCH v14 10/11] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2023-07-07 14:44                                                                                                                       ` [PATCH v14 11/11] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2023-07-07 17:35                                                                                                                         ` Simon Glass
2023-07-07 17:44                                                                                                                           ` Tom Rini
2023-07-07 18:09                                                                                                                             ` Simon Glass
2023-07-10 15:03                                                                                                                               ` Abdellatif El Khlifi
2023-07-10 16:18                                                                                                                                 ` Tom Rini
2023-07-13 13:28                                                                                                                                   ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
2023-07-13 13:28                                                                                                                                     ` [PATCH v15 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2023-07-13 13:28                                                                                                                                     ` [PATCH v15 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
2023-07-13 13:28                                                                                                                                     ` [PATCH v15 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
2023-07-13 13:28                                                                                                                                     ` [PATCH v15 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
2023-07-13 13:28                                                                                                                                     ` [PATCH v15 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
2023-07-13 13:28                                                                                                                                     ` [PATCH v15 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
2023-07-13 13:28                                                                                                                                     ` [PATCH v15 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2023-07-13 13:28                                                                                                                                     ` [PATCH v15 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2023-07-13 13:28                                                                                                                                     ` [PATCH v15 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2023-07-13 13:28                                                                                                                                     ` [PATCH v15 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2023-07-24 18:29                                                                                                                                     ` [PATCH v15 00/10] introduce Arm FF-A support Abdellatif El Khlifi
2023-07-24 23:01                                                                                                                                     ` Tom Rini
2023-07-24 23:50                                                                                                                                     ` Tom Rini
2023-07-25  9:26                                                                                                                                       ` Abdellatif El Khlifi
2023-07-25 13:47                                                                                                                                         ` Tom Rini
2023-07-25 18:34                                                                                                                                           ` Abdellatif El Khlifi
2023-07-25 18:52                                                                                                                                             ` Tom Rini
2023-07-26  9:44                                                                                                                                               ` [PATCH v16 " Abdellatif El Khlifi
2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
2023-07-27  9:56                                                                                                                                                   ` Ilias Apalodimas
2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
2023-07-26  9:44                                                                                                                                                 ` [PATCH v16 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2023-07-26 19:39                                                                                                                                                   ` Tom Rini
2023-07-27  9:34                                                                                                                                                     ` Abdellatif El Khlifi
2023-07-27 13:30                                                                                                                                                       ` Tom Rini
2023-07-27  9:58                                                                                                                                                   ` Ilias Apalodimas
2023-07-27 15:28                                                                                                                                                     ` Gowtham Suresh Kumar
2023-07-27 11:27                                                                                                                                                   ` Ilias Apalodimas
2023-07-27 12:36                                                                                                                                                     ` Abdellatif El Khlifi
2023-07-26  9:45                                                                                                                                                 ` [PATCH v16 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2023-07-26 16:06                                                                                                                                                   ` Tom Rini
2023-07-27 16:07                                                                                                                                                     ` [PATCH v17 00/10] introduce Arm FF-A support Abdellatif El Khlifi
2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 02/10] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 04/10] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2023-07-27 16:43                                                                                                                                                         ` Tom Rini
2023-07-28  9:37                                                                                                                                                           ` Abdellatif El Khlifi
2023-07-28 11:00                                                                                                                                                           ` Ilias Apalodimas
2023-07-28 13:54                                                                                                                                                             ` Tom Rini
2023-07-31  9:38                                                                                                                                                               ` Ilias Apalodimas
2023-07-31 11:46                                                                                                                                                                 ` Abdellatif El Khlifi
2023-07-31 17:07                                                                                                                                                                   ` Simon Glass
2023-08-01  8:24                                                                                                                                                                   ` Ilias Apalodimas
2023-08-01 15:00                                                                                                                                                                     ` Tom Rini
2023-08-01 16:10                                                                                                                                                                       ` Abdellatif El Khlifi
2023-08-01 16:19                                                                                                                                                                         ` Tom Rini
2023-08-02  6:51                                                                                                                                                                           ` Ilias Apalodimas
2023-08-02 12:52                                                                                                                                                                             ` Simon Glass
2023-08-02 13:02                                                                                                                                                                               ` Ilias Apalodimas
2023-08-02 13:08                                                                                                                                                                                 ` Simon Glass
2023-08-02 13:26                                                                                                                                                                                   ` Ilias Apalodimas
2023-08-02 13:34                                                                                                                                                                                     ` Simon Glass
2023-08-02 13:37                                                                                                                                                                                       ` Ilias Apalodimas
2023-08-02 13:41                                                                                                                                                                                         ` Simon Glass
2023-08-02 13:42                                                                                                                                                                                           ` Ilias Apalodimas
2023-08-02 13:44                                                                                                                                                                                             ` Simon Glass
2023-08-02 13:47                                                                                                                                                                                               ` Ilias Apalodimas
2023-08-02 13:55                                                                                                                                                                                                 ` Simon Glass
2023-08-02 13:59                                                                                                                                                                                                   ` Ilias Apalodimas
2023-08-02 16:10                                                                                                                                                                                                     ` Simon Glass
2023-08-02 15:38                                                                                                                                                                                                   ` Tom Rini
2023-08-03 16:03                                                                                                                                                                             ` [PATCH v18 0/9] introduce Arm FF-A support Abdellatif El Khlifi
2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 1/9] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 2/9] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 3/9] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 4/9] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 5/9] arm_ffa: introduce sandbox " Abdellatif El Khlifi
2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 6/9] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 7/9] arm_ffa: introduce armffa command Abdellatif El Khlifi
2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 8/9] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2023-08-03 17:13                                                                                                                                                                                 ` Tom Rini
2023-08-03 16:03                                                                                                                                                                               ` [PATCH v18 9/9] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2023-08-03 17:14                                                                                                                                                                                 ` Tom Rini
2023-08-04  9:22                                                                                                                                                                                   ` Abdellatif El Khlifi
2023-08-04 13:33                                                                                                                                                                                   ` [PATCH v19 0/9] introduce Arm FF-A support Abdellatif El Khlifi
2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 1/9] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Abdellatif El Khlifi
2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 2/9] lib: uuid: introduce uuid_str_to_le_bin function Abdellatif El Khlifi
2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 3/9] lib: uuid: introduce testcase for uuid_str_to_le_bin Abdellatif El Khlifi
2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 4/9] arm_ffa: introduce Arm FF-A support Abdellatif El Khlifi
2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 5/9] arm_ffa: introduce sandbox " Abdellatif El Khlifi
2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 6/9] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 7/9] arm_ffa: introduce armffa command Abdellatif El Khlifi
2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 8/9] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2023-08-04 18:35                                                                                                                                                                                       ` Tom Rini
2023-08-07 14:47                                                                                                                                                                                       ` Ilias Apalodimas
2023-08-07 15:26                                                                                                                                                                                         ` Abdellatif El Khlifi
2023-08-04 13:33                                                                                                                                                                                     ` [PATCH v19 9/9] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2023-08-04 18:35                                                                                                                                                                                     ` [PATCH v19 0/9] introduce Arm FF-A support Tom Rini
2023-08-07 15:30                                                                                                                                                                                       ` Abdellatif El Khlifi
2023-08-08 19:25                                                                                                                                                                                     ` Tom Rini
2023-08-09  2:03                                                                                                                                                                                       ` Simon Glass
2023-08-09 11:47                                                                                                                                                                                         ` [PATCH] arm_ffa: use debug logs Abdellatif El Khlifi
2023-08-10  1:15                                                                                                                                                                                           ` Simon Glass
2023-08-17 19:02                                                                                                                                                                                           ` Tom Rini
2023-08-02 12:50                                                                                                                                                                           ` [PATCH v17 09/10] arm_ffa: efi: introduce FF-A MM communication Simon Glass
2023-08-01 12:28                                                                                                                                                                   ` Jens Wiklander
2023-08-02 10:36                                                                                                                                                                     ` Abdellatif El Khlifi
2023-07-27 16:07                                                                                                                                                       ` [PATCH v17 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2023-06-16 15:28                                                                                                     ` [PATCH v13 06/10] arm_ffa: introduce sandbox FF-A support Abdellatif El Khlifi
2023-06-16 15:28                                                                                                     ` [PATCH v13 07/10] arm_ffa: introduce sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2023-06-16 15:28                                                                                                     ` [PATCH v13 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2023-06-16 15:28                                                                                                     ` [PATCH v13 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2023-06-20 10:27                                                                                                       ` Simon Glass
2023-06-21  6:21                                                                                                       ` Ilias Apalodimas
2023-06-16 15:28                                                                                                     ` [PATCH v13 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2023-01-19 16:46                                                                         ` [PATCH v8 03/10] arm_ffa: introduce Arm FF-A low-level driver Sudeep Holla
2023-01-19 16:54                                                                           ` Simon Glass
2023-01-19 16:57                                                                             ` Tom Rini
2023-01-19 17:09                                                                               ` Sudeep Holla
2023-01-19 17:21                                                                                 ` Tom Rini
2023-01-19 17:22                                                                                 ` Simon Glass
2023-01-20 11:17                                                                                   ` Sudeep Holla
2023-01-23 16:32                                                                                     ` Simon Glass
2023-01-24 11:30                                                                                       ` Sudeep Holla
2023-01-24 22:44                                                                                         ` Simon Glass
2023-01-25  7:39                                                                                           ` Sudeep Holla
2023-01-19 17:21                                                                               ` Simon Glass
2023-01-19 17:24                                                                                 ` Tom Rini
2023-01-19 18:04                                                                                   ` Simon Glass
2023-01-20 10:52                                                                                     ` Sudeep Holla
2023-01-19 17:00                                                                             ` Sudeep Holla
2022-11-22 13:17                                         ` [PATCH v8 04/10] arm_ffa: efi: unmap RX/TX buffers Abdellatif El Khlifi
2022-11-23  2:09                                           ` Simon Glass
2022-11-22 13:17                                         ` [PATCH v8 05/10] arm_ffa: introduce armffa command Abdellatif El Khlifi
2022-11-23  2:09                                           ` Simon Glass
2022-11-22 13:17                                         ` [PATCH v8 06/10] arm_ffa: introduce the FF-A Sandbox driver Abdellatif El Khlifi
2022-11-23  2:09                                           ` Simon Glass
2022-11-22 13:17                                         ` [PATCH v8 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Abdellatif El Khlifi
2022-11-23  2:09                                           ` Simon Glass
2022-11-22 13:17                                         ` [PATCH v8 08/10] arm_ffa: introduce armffa command Sandbox test Abdellatif El Khlifi
2022-11-23  2:09                                           ` Simon Glass
2022-11-22 13:17                                         ` [PATCH v8 09/10] arm_ffa: efi: introduce FF-A MM communication Abdellatif El Khlifi
2022-11-22 13:17                                         ` [PATCH v8 10/10] arm_ffa: efi: corstone1000: enable " Abdellatif El Khlifi
2022-08-01 19:13                 ` [PATCH 0/6] introduce Arm FF-A support Simon Glass
2022-08-01 19:28                   ` Sudeep Holla
2022-08-02  3:08                     ` Simon Glass
2022-08-02  8:38                       ` Sudeep Holla
2022-08-05 11:15                       ` Abdellatif El Khlifi
2022-08-05 16:48                         ` Simon Glass
2022-08-02 12:22                     ` Tom Rini
2022-08-02 13:45                       ` Sudeep Holla
2022-08-03 10:14                       ` Abdellatif El Khlifi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).