blob: c0078b80275f18ab602f92027298faa5e60eee24 [file] [log] [blame]
Patrick Williams44b3caf2024-04-12 16:51:14 -05001From b05ab0973850069d819872e26fae2aecbbf75f0e Mon Sep 17 00:00:00 2001
Patrick Williams2a254922023-08-11 09:48:11 -05002From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
3Date: Mon, 17 Jul 2023 15:18:58 +0100
Patrick Williams44b3caf2024-04-12 16:51:14 -05004Subject: [PATCH] FF-A v15: arm_ffa: introduce sandbox FF-A support
Patrick Williams2a254922023-08-11 09:48:11 -05005
6Emulate Secure World's FF-A ABIs and allow testing U-Boot FF-A support
7
8Features of the sandbox FF-A support:
9
10- Introduce an FF-A emulator
11- Introduce an FF-A device driver for FF-A comms with emulated Secure World
12- Provides test methods allowing to read the status of the inspected ABIs
13
14The sandbox FF-A emulator supports only 64-bit direct messaging.
15
16Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
17Reviewed-by: Simon Glass <sjg@chromium.org>
18Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/]
19---
20 MAINTAINERS | 3 +-
21 arch/sandbox/dts/sandbox.dtsi | 9 +
22 arch/sandbox/dts/test.dts | 9 +
23 arch/sandbox/include/asm/sandbox_arm_ffa.h | 72 ++
24 .../include/asm/sandbox_arm_ffa_priv.h | 121 +++
25 configs/sandbox64_defconfig | 2 +
26 configs/sandbox_defconfig | 2 +
27 doc/arch/arm64.ffa.rst | 19 +-
28 doc/arch/sandbox/sandbox.rst | 1 +
29 drivers/firmware/arm-ffa/Kconfig | 13 +-
30 drivers/firmware/arm-ffa/Makefile | 10 +-
31 drivers/firmware/arm-ffa/ffa-emul-uclass.c | 720 ++++++++++++++++++
32 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h | 14 -
33 drivers/firmware/arm-ffa/sandbox_ffa.c | 110 +++
34 include/dm/uclass-id.h | 1 +
35 15 files changed, 1084 insertions(+), 22 deletions(-)
36 create mode 100644 arch/sandbox/include/asm/sandbox_arm_ffa.h
37 create mode 100644 arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
38 create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
39 delete mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
40 create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c
41
42diff --git a/MAINTAINERS b/MAINTAINERS
43index 4ae82229fc..679a3acdd8 100644
44--- a/MAINTAINERS
45+++ b/MAINTAINERS
46@@ -269,12 +269,13 @@ F: configs/cortina_presidio-asic-pnand_defconfig
47 ARM FF-A
48 M: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
49 S: Maintained
50+F: arch/sandbox/include/asm/sandbox_arm_ffa.h
51+F: arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
52 F: cmd/armffa.c
53 F: doc/arch/arm64.ffa.rst
54 F: doc/usage/cmd/armffa.rst
55 F: drivers/firmware/arm-ffa/
56 F: include/arm_ffa.h
57-F: include/sandbox_arm_ffa.h
58
59 ARM FREESCALE IMX
60 M: Stefano Babic <sbabic@denx.de>
61diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
62index 30a305c4d2..94a08814b8 100644
63--- a/arch/sandbox/dts/sandbox.dtsi
64+++ b/arch/sandbox/dts/sandbox.dtsi
65@@ -445,6 +445,15 @@
66 thermal {
67 compatible = "sandbox,thermal";
68 };
69+
70+ arm-ffa-emul {
71+ compatible = "sandbox,arm-ffa-emul";
72+
73+ sandbox-arm-ffa {
74+ compatible = "sandbox,arm-ffa";
75+ };
76+ };
77+
78 };
79
80 &cros_ec {
81diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
82index ff9f9222e6..c6807ee031 100644
83--- a/arch/sandbox/dts/test.dts
84+++ b/arch/sandbox/dts/test.dts
85@@ -1820,6 +1820,15 @@
86 extcon {
87 compatible = "sandbox,extcon";
88 };
89+
90+ arm-ffa-emul {
91+ compatible = "sandbox,arm-ffa-emul";
92+
93+ sandbox-arm-ffa {
94+ compatible = "sandbox,arm-ffa";
95+ };
96+ };
97+
98 };
99
100 #include "sandbox_pmic.dtsi"
101diff --git a/arch/sandbox/include/asm/sandbox_arm_ffa.h b/arch/sandbox/include/asm/sandbox_arm_ffa.h
102new file mode 100644
103index 0000000000..be2790f496
104--- /dev/null
105+++ b/arch/sandbox/include/asm/sandbox_arm_ffa.h
106@@ -0,0 +1,72 @@
107+/* SPDX-License-Identifier: GPL-2.0+ */
108+/*
109+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
110+ *
111+ * Authors:
112+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
113+ */
114+
115+#ifndef __SANDBOX_ARM_FFA_H
116+#define __SANDBOX_ARM_FFA_H
117+
118+#include <arm_ffa.h>
119+
120+/*
121+ * This header provides public sandbox FF-A emulator declarations
122+ * and declarations needed by FF-A sandbox clients
123+ */
124+
125+/* UUIDs strings of the emulated services */
126+#define SANDBOX_SERVICE1_UUID "ed32d533-4209-99e6-2d72-cdd998a79cc0"
127+#define SANDBOX_SERVICE2_UUID "ed32d544-4209-99e6-2d72-cdd998a79cc0"
128+
129+/* IDs of the emulated secure partitions (SPs) */
130+#define SANDBOX_SP1_ID 0x1245
131+#define SANDBOX_SP2_ID 0x9836
132+#define SANDBOX_SP3_ID 0x6452
133+#define SANDBOX_SP4_ID 0x7814
134+
135+/* Invalid service UUID (no matching SP) */
136+#define SANDBOX_SERVICE3_UUID "55d532ed-0942-e699-722d-c09ca798d9cd"
137+
138+/* Invalid service UUID (invalid UUID string format) */
139+#define SANDBOX_SERVICE4_UUID "32ed-0942-e699-722d-c09ca798d9cd"
140+
141+/* Number of valid services */
142+#define SANDBOX_SP_COUNT_PER_VALID_SERVICE 2
143+
144+/**
145+ * struct ffa_sandbox_data - query ABI state data structure
146+ * @data0_size: size of the first argument
147+ * @data0: pointer to the first argument
148+ * @data1_size>: size of the second argument
149+ * @data1: pointer to the second argument
150+ *
151+ * Used to pass various types of data with different sizes between
152+ * the test cases and the sandbox emulator.
153+ * The data is for querying FF-A ABIs state.
154+ */
155+struct ffa_sandbox_data {
156+ u32 data0_size; /* size of the first argument */
157+ void *data0; /* pointer to the first argument */
158+ u32 data1_size; /* size of the second argument */
159+ void *data1; /* pointer to the second argument */
160+};
161+
162+/* The sandbox FF-A emulator public functions */
163+
164+/**
165+ * sandbox_query_ffa_emul_state() - Inspect the FF-A ABIs
166+ * @queried_func_id: The FF-A function to be queried
167+ * @func_data: Pointer to the FF-A function arguments container structure
168+ *
169+ * Query the status of FF-A ABI specified in the input argument.
170+ *
171+ * Return:
172+ *
173+ * 0 on success. Otherwise, failure
174+ */
175+int sandbox_query_ffa_emul_state(u32 queried_func_id,
176+ struct ffa_sandbox_data *func_data);
177+
178+#endif
179diff --git a/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
180new file mode 100644
181index 0000000000..b0881822d7
182--- /dev/null
183+++ b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
184@@ -0,0 +1,121 @@
185+/* SPDX-License-Identifier: GPL-2.0+ */
186+/*
187+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
188+ *
189+ * Authors:
190+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
191+ */
192+
193+#ifndef __SANDBOX_ARM_FFA_PRV_H
194+#define __SANDBOX_ARM_FFA_PRV_H
195+
196+#include <arm_ffa_priv.h>
197+
198+/* This header is exclusively used by the Sandbox FF-A driver and emulator */
199+
200+/* Non-secure physical FF-A instance */
201+#define NS_PHYS_ENDPOINT_ID (0)
202+
203+#define GET_NS_PHYS_ENDPOINT_ID_MASK GENMASK(31, 16)
204+#define GET_NS_PHYS_ENDPOINT_ID(x) \
205+ ((u16)(FIELD_GET(GET_NS_PHYS_ENDPOINT_ID_MASK, (x))))
206+
207+/* Helper macro for reading the destination partition ID */
208+#define GET_DST_SP_ID_MASK GENMASK(15, 0)
209+#define GET_DST_SP_ID(x) \
210+ ((u16)(FIELD_GET(GET_DST_SP_ID_MASK, (x))))
211+
212+/* Helper macro for setting the source partition ID */
213+#define PREP_SRC_SP_ID_MASK GENMASK(31, 16)
214+#define PREP_SRC_SP_ID(x) \
215+ (FIELD_PREP(PREP_SRC_SP_ID_MASK, (x)))
216+
217+/* Helper macro for setting the destination endpoint ID */
218+#define PREP_NS_PHYS_ENDPOINT_ID_MASK GENMASK(15, 0)
219+#define PREP_NS_PHYS_ENDPOINT_ID(x) \
220+ (FIELD_PREP(PREP_NS_PHYS_ENDPOINT_ID_MASK, (x)))
221+
222+/* RX/TX buffers minimum size */
223+#define RXTX_BUFFERS_MIN_SIZE (RXTX_4K)
224+#define RXTX_BUFFERS_MIN_PAGES (1)
225+
226+/* MBZ registers info */
227+
228+/* x1-x7 MBZ */
229+#define FFA_X1X7_MBZ_CNT (7)
230+#define FFA_X1X7_MBZ_REG_START (&res->a1)
231+
232+/* x4-x7 MBZ */
233+#define FFA_X4X7_MBZ_CNT (4)
234+#define FFA_X4X7_MBZ_REG_START (&res->a4)
235+
236+/* x3-x7 MBZ */
237+#define FFA_X3X7_MBZ_CNT (5)
238+#define FFA_X3_MBZ_REG_START (&res->a3)
239+
240+/* number of emulated FF-A secure partitions (SPs) */
241+#define SANDBOX_PARTITIONS_CNT (4)
242+
243+/* Binary data of the emulated services UUIDs */
244+
245+/* service 1 UUID binary data (little-endian format) */
246+#define SANDBOX_SERVICE1_UUID_A1 0xed32d533
247+#define SANDBOX_SERVICE1_UUID_A2 0x99e64209
248+#define SANDBOX_SERVICE1_UUID_A3 0x9cc02d72
249+#define SANDBOX_SERVICE1_UUID_A4 0xcdd998a7
250+
251+/* service 2 UUID binary data (little-endian format) */
252+#define SANDBOX_SERVICE2_UUID_A1 0xed32d544
253+#define SANDBOX_SERVICE2_UUID_A2 0x99e64209
254+#define SANDBOX_SERVICE2_UUID_A3 0x9cc02d72
255+#define SANDBOX_SERVICE2_UUID_A4 0xcdd998a7
256+
257+/**
258+ * struct ffa_rxtxpair_info - structure hosting the RX/TX buffers flags
259+ * @rxbuf_owned: RX buffer ownership flag (the owner is non secure world)
260+ * @rxbuf_mapped: RX buffer mapping flag
261+ * @txbuf_owned TX buffer ownership flag
262+ * @txbuf_mapped: TX buffer mapping flag
263+ * @rxtx_buf_size: RX/TX buffers size
264+ *
265+ * Hosts the ownership/mapping flags of the RX/TX buffers
266+ * When a buffer is owned/mapped its corresponding flag is set to 1 otherwise 0.
267+ */
268+struct ffa_rxtxpair_info {
269+ u8 rxbuf_owned;
270+ u8 rxbuf_mapped;
271+ u8 txbuf_owned;
272+ u8 txbuf_mapped;
273+ u32 rxtx_buf_size;
274+};
275+
276+/**
277+ * struct sandbox_ffa_emul - emulator data
278+ *
279+ * @fwk_version: FF-A framework version
280+ * @id: u-boot endpoint ID
281+ * @partitions: The partitions descriptors structure
282+ * @pair: The RX/TX buffers pair
283+ * @pair_info: The RX/TX buffers pair flags and size
284+ * @test_ffa_data: The data of the FF-A bus under test
285+ *
286+ * Hosts all the emulated secure world data.
287+ */
288+struct sandbox_ffa_emul {
289+ u32 fwk_version;
290+ u16 id;
291+ struct ffa_partitions partitions;
292+ struct ffa_rxtxpair pair;
293+ struct ffa_rxtxpair_info pair_info;
294+};
295+
296+/**
297+ * ffa_emul_find() - Finds the FF-A emulator
298+ * @dev: the sandbox FF-A device (sandbox-arm-ffa)
299+ * @emulp: the FF-A emulator device (sandbox-ffa-emul)
300+ * Return:
301+ * 0 on success. Otherwise, failure
302+ */
303+int ffa_emul_find(struct udevice *dev, struct udevice **emulp);
304+
305+#endif
306diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
307index 98b3e0cda4..2db69b8e52 100644
308--- a/configs/sandbox64_defconfig
309+++ b/configs/sandbox64_defconfig
310@@ -260,3 +260,5 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
311 CONFIG_UNIT_TEST=y
312 CONFIG_UT_TIME=y
313 CONFIG_UT_DM=y
314+CONFIG_NVMXIP_QSPI=y
315+CONFIG_ARM_FFA_TRANSPORT=y
316diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
317index 1ec44d5b33..f77733377d 100644
318--- a/configs/sandbox_defconfig
319+++ b/configs/sandbox_defconfig
320@@ -344,3 +344,5 @@ CONFIG_TEST_FDTDEC=y
321 CONFIG_UNIT_TEST=y
322 CONFIG_UT_TIME=y
323 CONFIG_UT_DM=y
324+CONFIG_CMD_2048=y
325+CONFIG_ARM_FFA_TRANSPORT=y
326diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
327index aefd527447..b7c754fa3d 100644
328--- a/doc/arch/arm64.ffa.rst
329+++ b/doc/arch/arm64.ffa.rst
330@@ -33,6 +33,10 @@ The U-Boot FF-A support provides the following parts:
331
332 - A Uclass driver providing generic FF-A methods.
333 - An Arm FF-A device driver providing Arm-specific methods and reusing the Uclass methods.
334+- A sandbox emulator for Arm FF-A, emulates the FF-A side of the Secure World and provides
335+ FF-A ABIs inspection methods.
336+- An FF-A sandbox device driver for FF-A communication with the emulated Secure World.
337+ The driver leverages the FF-A Uclass to establish FF-A communication.
338
339 FF-A and SMC specifications
340 -------------------------------------------
341@@ -62,6 +66,7 @@ CONFIG_ARM_FFA_TRANSPORT
342 Enables the FF-A support. Turn this on if you want to use FF-A
343 communication.
344 When using an Arm 64-bit platform, the Arm FF-A driver will be used.
345+ When using sandbox, the sandbox FF-A emulator and FF-A sandbox driver will be used.
346
347 FF-A ABIs under the hood
348 ---------------------------------------
349@@ -98,10 +103,8 @@ architecture features including FF-A bus.
350
351 Class Index Probed Driver Name
352 -----------------------------------------------------------
353- ...
354 firmware 0 [ + ] psci |-- psci
355 ffa 0 [ ] arm_ffa | `-- arm_ffa
356- ...
357
358 The PSCI driver is bound to the PSCI device and when probed it tries to discover
359 the architecture features by calling a callback the features drivers provide.
360@@ -205,6 +208,18 @@ The following features are provided:
361
362 - FF-A bus can be compiled and used without EFI
363
364+Relationship between the sandbox emulator and the FF-A device
365+---------------------------------------------------------------
366+
367+::
368+
369+ => dm tree
370+
371+ Class Index Probed Driver Name
372+ -----------------------------------------------------------
373+ ffa_emul 0 [ + ] sandbox_ffa_emul `-- arm-ffa-emul
374+ ffa 0 [ ] sandbox_arm_ffa `-- sandbox-arm-ffa
375+
376 The armffa command
377 -----------------------------------
378
379diff --git a/doc/arch/sandbox/sandbox.rst b/doc/arch/sandbox/sandbox.rst
380index 77ca6bc4cc..a3631de749 100644
381--- a/doc/arch/sandbox/sandbox.rst
382+++ b/doc/arch/sandbox/sandbox.rst
383@@ -200,6 +200,7 @@ Supported Drivers
384
385 U-Boot sandbox supports these emulations:
386
387+- Arm FF-A
388 - Block devices
389 - Chrome OS EC
390 - GPIO
391diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
392index a7d5392859..d75f8b53fd 100644
393--- a/drivers/firmware/arm-ffa/Kconfig
394+++ b/drivers/firmware/arm-ffa/Kconfig
395@@ -2,9 +2,9 @@
396
397 config ARM_FFA_TRANSPORT
398 bool "Enable Arm Firmware Framework for Armv8-A driver"
399- depends on DM && ARM64
400- select ARM_SMCCC
401- select ARM_SMCCC_FEATURES
402+ depends on DM && (ARM64 || SANDBOX)
403+ select ARM_SMCCC if !SANDBOX
404+ select ARM_SMCCC_FEATURES if !SANDBOX
405 imply CMD_ARMFFA
406 select LIB_UUID
407 select DEVRES
408@@ -33,5 +33,10 @@ config ARM_FFA_TRANSPORT
409 Generic FF-A methods are implemented in the Uclass (arm-ffa-uclass.c).
410 Arm specific methods are implemented in the Arm driver (arm-ffa.c).
411
412- For more details about the FF-A support, please refer to doc/arch/arm64.ffa.rst
413+ FF-A sandbox is provided to run FF-A under sandbox and allows to test the FF-A Uclass.
414+ Sandbox support includes an emulator for Arm FF-A which emulates the FF-A side of
415+ the Secure World and provides FF-A ABIs inspection methods (ffa-emul-uclass.c).
416+ An FF-A sandbox driver is also provided for FF-A communication with the emulated
417+ Secure World (sandbox_ffa.c).
418
419+ For more details about the FF-A support, please refer to doc/arch/arm64.ffa.rst
420diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
421index 11b1766285..318123a7f4 100644
422--- a/drivers/firmware/arm-ffa/Makefile
423+++ b/drivers/firmware/arm-ffa/Makefile
424@@ -5,4 +5,12 @@
425 # Authors:
426 # Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
427
428-obj-y += arm-ffa-uclass.o arm-ffa.o
429+# build the generic FF-A methods
430+obj-y += arm-ffa-uclass.o
431+ifeq ($(CONFIG_SANDBOX),y)
432+# build the FF-A sandbox emulator and driver
433+obj-y += ffa-emul-uclass.o sandbox_ffa.o
434+else
435+# build the Arm64 FF-A driver
436+obj-y += arm-ffa.o
437+endif
438diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
439new file mode 100644
440index 0000000000..5562bbaac3
441--- /dev/null
442+++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
443@@ -0,0 +1,720 @@
444+// SPDX-License-Identifier: GPL-2.0+
445+/*
446+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
447+ *
448+ * Authors:
449+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
450+ */
451+#include <common.h>
452+#include <dm.h>
453+#include <mapmem.h>
454+#include <string.h>
455+#include <asm/global_data.h>
456+#include <asm/sandbox_arm_ffa.h>
457+#include <asm/sandbox_arm_ffa_priv.h>
458+#include <dm/device-internal.h>
459+#include <dm/lists.h>
460+#include <dm/root.h>
461+#include <linux/errno.h>
462+#include <linux/sizes.h>
463+
464+DECLARE_GLOBAL_DATA_PTR;
465+
466+/* The partitions (SPs) table */
467+static struct ffa_partition_desc sandbox_partitions[SANDBOX_PARTITIONS_CNT] = {
468+ {
469+ .info = { .id = SANDBOX_SP1_ID, .exec_ctxt = 0x5687, .properties = 0x89325621 },
470+ .sp_uuid = {
471+ .a1 = SANDBOX_SERVICE1_UUID_A1,
472+ .a2 = SANDBOX_SERVICE1_UUID_A2,
473+ .a3 = SANDBOX_SERVICE1_UUID_A3,
474+ .a4 = SANDBOX_SERVICE1_UUID_A4,
475+ }
476+ },
477+ {
478+ .info = { .id = SANDBOX_SP3_ID, .exec_ctxt = 0x7687, .properties = 0x23325621 },
479+ .sp_uuid = {
480+ .a1 = SANDBOX_SERVICE2_UUID_A1,
481+ .a2 = SANDBOX_SERVICE2_UUID_A2,
482+ .a3 = SANDBOX_SERVICE2_UUID_A3,
483+ .a4 = SANDBOX_SERVICE2_UUID_A4,
484+ }
485+ },
486+ {
487+ .info = { .id = SANDBOX_SP2_ID, .exec_ctxt = 0x9587, .properties = 0x45325621 },
488+ .sp_uuid = {
489+ .a1 = SANDBOX_SERVICE1_UUID_A1,
490+ .a2 = SANDBOX_SERVICE1_UUID_A2,
491+ .a3 = SANDBOX_SERVICE1_UUID_A3,
492+ .a4 = SANDBOX_SERVICE1_UUID_A4,
493+ }
494+ },
495+ {
496+ .info = { .id = SANDBOX_SP4_ID, .exec_ctxt = 0x1487, .properties = 0x70325621 },
497+ .sp_uuid = {
498+ .a1 = SANDBOX_SERVICE2_UUID_A1,
499+ .a2 = SANDBOX_SERVICE2_UUID_A2,
500+ .a3 = SANDBOX_SERVICE2_UUID_A3,
501+ .a4 = SANDBOX_SERVICE2_UUID_A4,
502+ }
503+ }
504+
505+};
506+
507+/* The emulator functions */
508+
509+/**
510+ * sandbox_ffa_version() - Emulated FFA_VERSION handler function
511+ * @emul: The sandbox FF-A emulator device
512+ * @pargs: The SMC call input arguments a0-a7
513+ * @res: The SMC return data
514+ *
515+ * Emulate FFA_VERSION FF-A function.
516+ *
517+ * Return:
518+ *
519+ * 0 on success. Otherwise, failure
520+ */
521+
522+static int sandbox_ffa_version(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res)
523+{
524+ struct sandbox_ffa_emul *priv = dev_get_priv(emul);
525+
526+ priv->fwk_version = FFA_VERSION_1_0;
527+ res->a0 = priv->fwk_version;
528+
529+ /* x1-x7 MBZ */
530+ memset(FFA_X1X7_MBZ_REG_START, 0, FFA_X1X7_MBZ_CNT * sizeof(ulong));
531+
532+ return 0;
533+}
534+
535+/**
536+ * sandbox_ffa_id_get() - Emulated FFA_ID_GET handler function
537+ * @emul: The sandbox FF-A emulator device
538+ * @pargs: The SMC call input arguments a0-a7
539+ * @res: The SMC return data
540+ *
541+ * Emulate FFA_ID_GET FF-A function.
542+ *
543+ * Return:
544+ *
545+ * 0 on success. Otherwise, failure
546+ */
547+static int sandbox_ffa_id_get(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res)
548+{
549+ struct sandbox_ffa_emul *priv = dev_get_priv(emul);
550+
551+ res->a0 = FFA_SMC_32(FFA_SUCCESS);
552+ res->a1 = 0;
553+
554+ priv->id = NS_PHYS_ENDPOINT_ID;
555+ res->a2 = priv->id;
556+
557+ /* x3-x7 MBZ */
558+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
559+
560+ return 0;
561+}
562+
563+/**
564+ * sandbox_ffa_features() - Emulated FFA_FEATURES handler function
565+ * @pargs: The SMC call input arguments a0-a7
566+ * @res: The SMC return data
567+ *
568+ * Emulate FFA_FEATURES FF-A function.
569+ *
570+ * Return:
571+ *
572+ * 0 on success. Otherwise, failure
573+ */
574+static int sandbox_ffa_features(ffa_value_t *pargs, ffa_value_t *res)
575+{
576+ res->a1 = 0;
577+
578+ if (pargs->a1 == FFA_SMC_64(FFA_RXTX_MAP)) {
579+ res->a0 = FFA_SMC_32(FFA_SUCCESS);
580+ res->a2 = RXTX_BUFFERS_MIN_SIZE;
581+ res->a3 = 0;
582+ /* x4-x7 MBZ */
583+ memset(FFA_X4X7_MBZ_REG_START, 0, FFA_X4X7_MBZ_CNT * sizeof(ulong));
584+ return 0;
585+ }
586+
587+ res->a0 = FFA_SMC_32(FFA_ERROR);
588+ res->a2 = -NOT_SUPPORTED;
589+ /* x3-x7 MBZ */
590+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
591+ log_err("FF-A interface %lx not implemented\n", pargs->a1);
592+
593+ return ffa_to_std_errmap[NOT_SUPPORTED];
594+}
595+
596+/**
597+ * sandbox_ffa_partition_info_get() - Emulated FFA_PARTITION_INFO_GET handler
598+ * @emul: The sandbox FF-A emulator device
599+ * @pargs: The SMC call input arguments a0-a7
600+ * @res: The SMC return data
601+ *
602+ * Emulate FFA_PARTITION_INFO_GET FF-A function.
603+ *
604+ * Return:
605+ *
606+ * 0 on success. Otherwise, failure
607+ */
608+static int sandbox_ffa_partition_info_get(struct udevice *emul, ffa_value_t *pargs,
609+ ffa_value_t *res)
610+{
611+ struct ffa_partition_info *rxbuf_desc_info = NULL;
612+ u32 descs_cnt;
613+ u32 descs_size_bytes;
614+ int ret;
615+ struct sandbox_ffa_emul *priv = dev_get_priv(emul);
616+
617+ res->a0 = FFA_SMC_32(FFA_ERROR);
618+
619+ if (!priv->pair.rxbuf) {
620+ res->a2 = -DENIED;
621+ ret = ffa_to_std_errmap[DENIED];
622+ goto cleanup;
623+ }
624+
625+ if (priv->pair_info.rxbuf_owned) {
626+ res->a2 = -BUSY;
627+ ret = ffa_to_std_errmap[BUSY];
628+ goto cleanup;
629+ }
630+
631+ if (!priv->partitions.descs) {
632+ priv->partitions.descs = sandbox_partitions;
633+ priv->partitions.count = SANDBOX_PARTITIONS_CNT;
634+ }
635+
636+ descs_size_bytes = SANDBOX_PARTITIONS_CNT *
637+ sizeof(struct ffa_partition_desc);
638+
639+ /* Abort if the RX buffer size is smaller than the descs buffer size */
640+ if ((priv->pair_info.rxtx_buf_size * SZ_4K) < descs_size_bytes) {
641+ res->a2 = -NO_MEMORY;
642+ ret = ffa_to_std_errmap[NO_MEMORY];
643+ goto cleanup;
644+ }
645+
646+ rxbuf_desc_info = priv->pair.rxbuf;
647+
648+ /* No UUID specified. Return the information of all partitions */
649+ if (!pargs->a1 && !pargs->a2 && !pargs->a3 && !pargs->a4) {
650+ for (descs_cnt = 0; descs_cnt < SANDBOX_PARTITIONS_CNT; descs_cnt++)
651+ *(rxbuf_desc_info++) = priv->partitions.descs[descs_cnt].info;
652+
653+ res->a0 = FFA_SMC_32(FFA_SUCCESS);
654+ res->a2 = SANDBOX_PARTITIONS_CNT;
655+ /* Transfer ownership to the consumer: the non secure world */
656+ priv->pair_info.rxbuf_owned = 1;
657+ ret = 0;
658+
659+ goto cleanup;
660+ }
661+
662+ /* A UUID specified. Return the info of all SPs matching the UUID */
663+
664+ for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++)
665+ if (pargs->a1 == priv->partitions.descs[descs_cnt].sp_uuid.a1 &&
666+ pargs->a2 == priv->partitions.descs[descs_cnt].sp_uuid.a2 &&
667+ pargs->a3 == priv->partitions.descs[descs_cnt].sp_uuid.a3 &&
668+ pargs->a4 == priv->partitions.descs[descs_cnt].sp_uuid.a4) {
669+ *(rxbuf_desc_info++) = priv->partitions.descs[descs_cnt].info;
670+ }
671+
672+ if (rxbuf_desc_info != priv->pair.rxbuf) {
673+ res->a0 = FFA_SMC_32(FFA_SUCCESS);
674+ /* Store the partitions count */
675+ res->a2 = (ulong)
676+ (rxbuf_desc_info - (struct ffa_partition_info *)
677+ priv->pair.rxbuf);
678+ ret = 0;
679+
680+ /* Transfer ownership to the consumer: the non secure world */
681+ priv->pair_info.rxbuf_owned = 1;
682+ } else {
683+ /* Unrecognized UUID */
684+ res->a2 = -INVALID_PARAMETERS;
685+ ret = ffa_to_std_errmap[INVALID_PARAMETERS];
686+ }
687+
688+cleanup:
689+
690+ log_err("FFA_PARTITION_INFO_GET (%ld)\n", res->a2);
691+
692+ res->a1 = 0;
693+
694+ /* x3-x7 MBZ */
695+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
696+
697+ return ret;
698+}
699+
700+/**
701+ * sandbox_ffa_rxtx_map() - Emulated FFA_RXTX_MAP handler
702+ * @emul: The sandbox FF-A emulator device
703+ * @pargs: The SMC call input arguments a0-a7
704+ * @res: The SMC return data
705+ *
706+ * Emulate FFA_RXTX_MAP FF-A function.
707+ *
708+ * Return:
709+ *
710+ * 0 on success. Otherwise, failure
711+ */
712+static int sandbox_ffa_rxtx_map(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res)
713+{
714+ int ret;
715+ struct sandbox_ffa_emul *priv = dev_get_priv(emul);
716+
717+ res->a0 = FFA_SMC_32(FFA_ERROR);
718+
719+ if (priv->pair.txbuf && priv->pair.rxbuf) {
720+ res->a2 = -DENIED;
721+ ret = ffa_to_std_errmap[DENIED];
722+ goto feedback;
723+ }
724+
725+ if (pargs->a3 >= RXTX_BUFFERS_MIN_PAGES && pargs->a1 && pargs->a2) {
726+ priv->pair.txbuf = map_sysmem(pargs->a1, 0);
727+ priv->pair.rxbuf = map_sysmem(pargs->a2, 0);
728+ priv->pair_info.rxtx_buf_size = pargs->a3;
729+ priv->pair_info.rxbuf_mapped = 1;
730+ res->a0 = FFA_SMC_32(FFA_SUCCESS);
731+ res->a2 = 0;
732+ ret = 0;
733+ goto feedback;
734+ }
735+
736+ if (!pargs->a1 || !pargs->a2) {
737+ res->a2 = -INVALID_PARAMETERS;
738+ ret = ffa_to_std_errmap[INVALID_PARAMETERS];
739+ } else {
740+ res->a2 = -NO_MEMORY;
741+ ret = ffa_to_std_errmap[NO_MEMORY];
742+ }
743+
744+ log_err("Error in FFA_RXTX_MAP arguments (%d)\n",
745+ (int)res->a2);
746+
747+feedback:
748+
749+ res->a1 = 0;
750+
751+ /* x3-x7 MBZ */
752+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
753+
754+ return ret;
755+}
756+
757+/**
758+ * sandbox_ffa_rxtx_unmap() - Emulated FFA_RXTX_UNMAP handler
759+ * @emul: The sandbox FF-A emulator device
760+ * @pargs: The SMC call input arguments a0-a7
761+ * @res: The SMC return data
762+ *
763+ * Emulate FFA_RXTX_UNMAP FF-A function.
764+ *
765+ * Return:
766+ *
767+ * 0 on success. Otherwise, failure
768+ */
769+static int sandbox_ffa_rxtx_unmap(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res)
770+{
771+ int ret;
772+ struct sandbox_ffa_emul *priv = dev_get_priv(emul);
773+
774+ res->a0 = FFA_SMC_32(FFA_ERROR);
775+ res->a2 = -INVALID_PARAMETERS;
776+ ret = ffa_to_std_errmap[INVALID_PARAMETERS];
777+
778+ if (GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id)
779+ goto feedback;
780+
781+ if (priv->pair.txbuf && priv->pair.rxbuf) {
782+ priv->pair.txbuf = 0;
783+ priv->pair.rxbuf = 0;
784+ priv->pair_info.rxtx_buf_size = 0;
785+ priv->pair_info.rxbuf_mapped = 0;
786+ res->a0 = FFA_SMC_32(FFA_SUCCESS);
787+ res->a2 = 0;
788+ ret = 0;
789+ goto feedback;
790+ }
791+
792+ log_err("No buffer pair registered on behalf of the caller\n");
793+
794+feedback:
795+
796+ res->a1 = 0;
797+
798+ /* x3-x7 MBZ */
799+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
800+
801+ return ret;
802+}
803+
804+/**
805+ * sandbox_ffa_rx_release() - Emulated FFA_RX_RELEASE handler
806+ * @emul: The sandbox FF-A emulator device
807+ * @pargs: The SMC call input arguments a0-a7
808+ * @res: The SMC return data
809+ *
810+ * Emulate FFA_RX_RELEASE FF-A function.
811+ *
812+ * Return:
813+ *
814+ * 0 on success. Otherwise, failure
815+ */
816+static int sandbox_ffa_rx_release(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res)
817+{
818+ int ret;
819+ struct sandbox_ffa_emul *priv = dev_get_priv(emul);
820+
821+ if (!priv->pair_info.rxbuf_owned) {
822+ res->a0 = FFA_SMC_32(FFA_ERROR);
823+ res->a2 = -DENIED;
824+ ret = ffa_to_std_errmap[DENIED];
825+ } else {
826+ priv->pair_info.rxbuf_owned = 0;
827+ res->a0 = FFA_SMC_32(FFA_SUCCESS);
828+ res->a2 = 0;
829+ ret = 0;
830+ }
831+
832+ res->a1 = 0;
833+
834+ /* x3-x7 MBZ */
835+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
836+
837+ return ret;
838+}
839+
840+/**
841+ * sandbox_ffa_sp_valid() - Check SP validity
842+ * @emul: The sandbox FF-A emulator device
843+ * @part_id: partition ID to check
844+ *
845+ * Search the input ID in the descriptors table.
846+ *
847+ * Return:
848+ *
849+ * 1 on success (Partition found). Otherwise, failure
850+ */
851+static int sandbox_ffa_sp_valid(struct udevice *emul, u16 part_id)
852+{
853+ u32 descs_cnt;
854+ struct sandbox_ffa_emul *priv = dev_get_priv(emul);
855+
856+ for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++)
857+ if (priv->partitions.descs[descs_cnt].info.id == part_id)
858+ return 1;
859+
860+ return 0;
861+}
862+
863+/**
864+ * sandbox_ffa_msg_send_direct_req() - Emulated FFA_MSG_SEND_DIRECT_{REQ,RESP} handler
865+ * @emul: The sandbox FF-A emulator device
866+ * @pargs: The SMC call input arguments a0-a7
867+ * @res: The SMC return data
868+ *
869+ * Emulate FFA_MSG_SEND_DIRECT_{REQ,RESP} FF-A ABIs.
870+ * Only SMC 64-bit is supported in Sandbox.
871+ *
872+ * Emulating interrupts is not supported. So, FFA_RUN and FFA_INTERRUPT are not
873+ * supported. In case of success FFA_MSG_SEND_DIRECT_RESP is returned with
874+ * default pattern data (0xff).
875+ *
876+ * Return:
877+ *
878+ * 0 on success. Otherwise, failure
879+ */
880+static int sandbox_ffa_msg_send_direct_req(struct udevice *emul,
881+ ffa_value_t *pargs, ffa_value_t *res)
882+{
883+ u16 part_id;
884+ struct sandbox_ffa_emul *priv = dev_get_priv(emul);
885+
886+ part_id = GET_DST_SP_ID(pargs->a1);
887+
888+ if (GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id ||
889+ !sandbox_ffa_sp_valid(emul, part_id) || pargs->a2) {
890+ res->a0 = FFA_SMC_32(FFA_ERROR);
891+ res->a1 = 0;
892+ res->a2 = -INVALID_PARAMETERS;
893+
894+ /* x3-x7 MBZ */
895+ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
896+
897+ return ffa_to_std_errmap[INVALID_PARAMETERS];
898+ }
899+
900+ res->a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
901+
902+ res->a1 = PREP_SRC_SP_ID(part_id) |
903+ PREP_NS_PHYS_ENDPOINT_ID(priv->id);
904+
905+ res->a2 = 0;
906+
907+ /* Return 0xff bytes as a response */
908+ res->a3 = -1UL;
909+ res->a4 = -1UL;
910+ res->a5 = -1UL;
911+ res->a6 = -1UL;
912+ res->a7 = -1UL;
913+
914+ return 0;
915+}
916+
917+/**
918+ * sandbox_ffa_get_rxbuf_flags() - Read the mapping/ownership flags
919+ * @emul: The sandbox FF-A emulator device
920+ * @queried_func_id: The FF-A function to be queried
921+ * @func_data: Pointer to the FF-A function arguments container structure
922+ *
923+ * Query the status flags of the following emulated
924+ * ABIs: FFA_RXTX_MAP, FFA_RXTX_UNMAP, FFA_RX_RELEASE.
925+ *
926+ * Return:
927+ *
928+ * 0 on success. Otherwise, failure
929+ */
930+static int sandbox_ffa_get_rxbuf_flags(struct udevice *emul, u32 queried_func_id,
931+ struct ffa_sandbox_data *func_data)
932+{
933+ struct sandbox_ffa_emul *priv = dev_get_priv(emul);
934+
935+ if (!func_data)
936+ return -EINVAL;
937+
938+ if (!func_data->data0 || func_data->data0_size != sizeof(u8))
939+ return -EINVAL;
940+
941+ switch (queried_func_id) {
942+ case FFA_RXTX_MAP:
943+ case FFA_RXTX_UNMAP:
944+ *((u8 *)func_data->data0) = priv->pair_info.rxbuf_mapped;
945+ return 0;
946+ case FFA_RX_RELEASE:
947+ *((u8 *)func_data->data0) = priv->pair_info.rxbuf_owned;
948+ return 0;
949+ default:
950+ log_err("The querried FF-A interface flag (%d) undefined\n",
951+ queried_func_id);
952+ return -EINVAL;
953+ }
954+}
955+
956+/**
957+ * sandbox_ffa_get_fwk_version() - Return the FFA framework version
958+ * @emul: The sandbox FF-A emulator device
959+ * @func_data: Pointer to the FF-A function arguments container structure
960+ *
961+ * Return the FFA framework version read from the FF-A emulator data.
962+ *
963+ * Return:
964+ *
965+ * 0 on success. Otherwise, failure
966+ */
967+static int sandbox_ffa_get_fwk_version(struct udevice *emul, struct ffa_sandbox_data *func_data)
968+{
969+ struct sandbox_ffa_emul *priv = dev_get_priv(emul);
970+
971+ if (!func_data)
972+ return -EINVAL;
973+
974+ if (!func_data->data0 ||
975+ func_data->data0_size != sizeof(priv->fwk_version))
976+ return -EINVAL;
977+
978+ *((u32 *)func_data->data0) = priv->fwk_version;
979+
980+ return 0;
981+}
982+
983+/**
984+ * sandbox_ffa_get_parts() - Return the address of partitions data
985+ * @emul: The sandbox FF-A emulator device
986+ * @func_data: Pointer to the FF-A function arguments container structure
987+ *
988+ * Return the address of partitions data read from the FF-A emulator data.
989+ *
990+ * Return:
991+ *
992+ * 0 on success. Otherwise, failure
993+ */
994+static int sandbox_ffa_get_parts(struct udevice *emul, struct ffa_sandbox_data *func_data)
995+{
996+ struct sandbox_ffa_emul *priv = dev_get_priv(emul);
997+
998+ if (!func_data)
999+ return -EINVAL;
1000+
1001+ if (!func_data->data0 ||
1002+ func_data->data0_size != sizeof(struct ffa_partitions *))
1003+ return -EINVAL;
1004+
1005+ *((struct ffa_partitions **)func_data->data0) = &priv->partitions;
1006+
1007+ return 0;
1008+}
1009+
1010+/**
1011+ * sandbox_query_ffa_emul_state() - Inspect the FF-A ABIs
1012+ * @queried_func_id: The FF-A function to be queried
1013+ * @func_data: Pointer to the FF-A function arguments container structure
1014+ *
1015+ * Query the status of FF-A ABI specified in the input argument.
1016+ *
1017+ * Return:
1018+ *
1019+ * 0 on success. Otherwise, failure
1020+ */
1021+int sandbox_query_ffa_emul_state(u32 queried_func_id,
1022+ struct ffa_sandbox_data *func_data)
1023+{
1024+ struct udevice *emul;
1025+ int ret;
1026+
1027+ ret = uclass_first_device_err(UCLASS_FFA_EMUL, &emul);
1028+ if (ret) {
1029+ log_err("Cannot find FF-A emulator during querying state\n");
1030+ return ret;
1031+ }
1032+
1033+ switch (queried_func_id) {
1034+ case FFA_RXTX_MAP:
1035+ case FFA_RXTX_UNMAP:
1036+ case FFA_RX_RELEASE:
1037+ return sandbox_ffa_get_rxbuf_flags(emul, queried_func_id, func_data);
1038+ case FFA_VERSION:
1039+ return sandbox_ffa_get_fwk_version(emul, func_data);
1040+ case FFA_PARTITION_INFO_GET:
1041+ return sandbox_ffa_get_parts(emul, func_data);
1042+ default:
1043+ log_err("Undefined FF-A interface (%d)\n",
1044+ queried_func_id);
1045+ return -EINVAL;
1046+ }
1047+}
1048+
1049+/**
1050+ * sandbox_arm_ffa_smccc_smc() - FF-A SMC call emulation
1051+ * @args: the SMC call arguments
1052+ * @res: the SMC call returned data
1053+ *
1054+ * Emulate the FF-A ABIs SMC call.
1055+ * The emulated FF-A ABI is identified and invoked.
1056+ * FF-A emulation is based on the FF-A specification 1.0
1057+ *
1058+ * Return:
1059+ *
1060+ * 0 on success. Otherwise, failure.
1061+ * FF-A protocol error codes are returned using the registers arguments as
1062+ * described by the specification
1063+ */
1064+void sandbox_arm_ffa_smccc_smc(ffa_value_t *args, ffa_value_t *res)
1065+{
1066+ int ret = 0;
1067+ struct udevice *emul;
1068+
1069+ ret = uclass_first_device_err(UCLASS_FFA_EMUL, &emul);
1070+ if (ret) {
1071+ log_err("Cannot find FF-A emulator during SMC emulation\n");
1072+ return;
1073+ }
1074+
1075+ switch (args->a0) {
1076+ case FFA_SMC_32(FFA_VERSION):
1077+ ret = sandbox_ffa_version(emul, args, res);
1078+ break;
1079+ case FFA_SMC_32(FFA_PARTITION_INFO_GET):
1080+ ret = sandbox_ffa_partition_info_get(emul, args, res);
1081+ break;
1082+ case FFA_SMC_32(FFA_RXTX_UNMAP):
1083+ ret = sandbox_ffa_rxtx_unmap(emul, args, res);
1084+ break;
1085+ case FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ):
1086+ ret = sandbox_ffa_msg_send_direct_req(emul, args, res);
1087+ break;
1088+ case FFA_SMC_32(FFA_ID_GET):
1089+ ret = sandbox_ffa_id_get(emul, args, res);
1090+ break;
1091+ case FFA_SMC_32(FFA_FEATURES):
1092+ ret = sandbox_ffa_features(args, res);
1093+ break;
1094+ case FFA_SMC_64(FFA_RXTX_MAP):
1095+ ret = sandbox_ffa_rxtx_map(emul, args, res);
1096+ break;
1097+ case FFA_SMC_32(FFA_RX_RELEASE):
1098+ ret = sandbox_ffa_rx_release(emul, args, res);
1099+ break;
1100+ default:
1101+ log_err("Undefined FF-A interface (%lx)\n",
1102+ args->a0);
1103+ }
1104+
1105+ if (ret != 0)
1106+ log_err("FF-A ABI internal failure (%d)\n", ret);
1107+}
1108+
1109+/**
1110+ * invoke_ffa_fn() - SMC wrapper
1111+ * @args: FF-A ABI arguments to be copied to Xn registers
1112+ * @res: FF-A ABI return data to be copied from Xn registers
1113+ *
1114+ * Calls the emulated SMC call.
1115+ */
1116+void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
1117+{
1118+ sandbox_arm_ffa_smccc_smc(&args, res);
1119+}
1120+
1121+/**
1122+ * ffa_emul_find() - Find the FF-A emulator
1123+ * @dev: the sandbox FF-A device (sandbox-arm-ffa)
1124+ * @emulp: the FF-A emulator device (sandbox-ffa-emul)
1125+ *
1126+ * Search for the FF-A emulator and returns its device pointer.
1127+ *
1128+ * Return:
1129+ * 0 on success. Otherwise, failure
1130+ */
1131+int ffa_emul_find(struct udevice *dev, struct udevice **emulp)
1132+{
1133+ int ret;
1134+
1135+ ret = uclass_first_device_err(UCLASS_FFA_EMUL, emulp);
1136+ if (ret) {
1137+ log_err("Cannot find FF-A emulator\n");
1138+ return ret;
1139+ }
1140+
1141+ log_info("FF-A emulator ready to use\n");
1142+
1143+ return 0;
1144+}
1145+
1146+UCLASS_DRIVER(ffa_emul) = {
1147+ .name = "ffa_emul",
1148+ .id = UCLASS_FFA_EMUL,
1149+ .post_bind = dm_scan_fdt_dev,
1150+};
1151+
1152+static const struct udevice_id sandbox_ffa_emul_ids[] = {
1153+ { .compatible = "sandbox,arm-ffa-emul" },
1154+ { }
1155+};
1156+
1157+/* Declaring the sandbox FF-A emulator under UCLASS_FFA_EMUL */
1158+U_BOOT_DRIVER(sandbox_ffa_emul) = {
1159+ .name = "sandbox_ffa_emul",
1160+ .id = UCLASS_FFA_EMUL,
1161+ .of_match = sandbox_ffa_emul_ids,
1162+ .priv_auto = sizeof(struct sandbox_ffa_emul),
1163+};
1164diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
1165deleted file mode 100644
1166index 4338f9c9b1..0000000000
1167--- a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
1168+++ /dev/null
1169@@ -1,14 +0,0 @@
1170-/* SPDX-License-Identifier: GPL-2.0+ */
1171-/*
1172- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
1173- *
1174- * Authors:
1175- * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
1176- */
1177-
1178-#ifndef __SANDBOX_ARM_FFA_PRV_H
1179-#define __SANDBOX_ARM_FFA_PRV_H
1180-
1181-/* Future sandbox support private declarations */
1182-
1183-#endif
1184diff --git a/drivers/firmware/arm-ffa/sandbox_ffa.c b/drivers/firmware/arm-ffa/sandbox_ffa.c
1185new file mode 100644
1186index 0000000000..ef9491ccea
1187--- /dev/null
1188+++ b/drivers/firmware/arm-ffa/sandbox_ffa.c
1189@@ -0,0 +1,110 @@
1190+// SPDX-License-Identifier: GPL-2.0+
1191+/*
1192+ * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
1193+ *
1194+ * Authors:
1195+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
1196+ */
1197+#include <common.h>
1198+#include <arm_ffa.h>
1199+#include <dm.h>
1200+#include <log.h>
1201+#include <asm/global_data.h>
1202+#include <asm/sandbox_arm_ffa_priv.h>
1203+#include <dm/device-internal.h>
1204+#include <linux/errno.h>
1205+
1206+DECLARE_GLOBAL_DATA_PTR;
1207+
1208+/**
1209+ * sandbox_ffa_discover() - perform sandbox FF-A discovery
1210+ * @dev: The sandbox FF-A bus device
1211+ * Try to discover the FF-A framework. Discovery is performed by
1212+ * querying the FF-A framework version from secure world using the FFA_VERSION ABI.
1213+ * Return:
1214+ *
1215+ * 0 on success. Otherwise, failure
1216+ */
1217+static int sandbox_ffa_discover(struct udevice *dev)
1218+{
1219+ int ret;
1220+ struct udevice *emul;
1221+
1222+ log_info("Emulated FF-A framework discovery\n");
1223+
1224+ ret = ffa_emul_find(dev, &emul);
1225+ if (ret) {
1226+ log_err("Cannot find FF-A emulator\n");
1227+ return ret;
1228+ }
1229+
1230+ ret = ffa_get_version_hdlr(dev);
1231+ if (ret)
1232+ return ret;
1233+
1234+ return 0;
1235+}
1236+
1237+/**
1238+ * sandbox_ffa_probe() - The sandbox FF-A driver probe function
1239+ * @dev: the sandbox-arm-ffa device
1240+ * Save the emulator device in uc_priv.
1241+ * Return:
1242+ *
1243+ * 0 on success.
1244+ */
1245+static int sandbox_ffa_probe(struct udevice *dev)
1246+{
1247+ int ret;
1248+ struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
1249+
1250+ ret = uclass_first_device_err(UCLASS_FFA_EMUL, &uc_priv->emul);
1251+ if (ret) {
1252+ log_err("Cannot find FF-A emulator\n");
1253+ return ret;
1254+ }
1255+
1256+ return 0;
1257+}
1258+
1259+/**
1260+ * sandbox_ffa_bind() - The sandbox FF-A driver bind function
1261+ * @dev: the sandbox-arm-ffa device
1262+ * Try to discover the emulated FF-A bus.
1263+ * Return:
1264+ *
1265+ * 0 on success.
1266+ */
1267+static int sandbox_ffa_bind(struct udevice *dev)
1268+{
1269+ int ret;
1270+
1271+ ret = sandbox_ffa_discover(dev);
1272+ if (ret)
1273+ return ret;
1274+
1275+ return 0;
1276+}
1277+
1278+/* Sandbox Arm FF-A emulator operations */
1279+
1280+static const struct ffa_bus_ops sandbox_ffa_ops = {
1281+ .partition_info_get = ffa_get_partitions_info_hdlr,
1282+ .sync_send_receive = ffa_msg_send_direct_req_hdlr,
1283+ .rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr,
1284+};
1285+
1286+static const struct udevice_id sandbox_ffa_id[] = {
1287+ { "sandbox,arm-ffa", 0 },
1288+ { },
1289+};
1290+
1291+/* Declaring the sandbox FF-A driver under UCLASS_FFA */
1292+U_BOOT_DRIVER(sandbox_arm_ffa) = {
1293+ .name = "sandbox_arm_ffa",
1294+ .of_match = sandbox_ffa_id,
1295+ .id = UCLASS_FFA,
1296+ .bind = sandbox_ffa_bind,
1297+ .probe = sandbox_ffa_probe,
1298+ .ops = &sandbox_ffa_ops,
1299+};
1300diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
1301index 3c6af2e3d2..0432c95c9e 100644
1302--- a/include/dm/uclass-id.h
1303+++ b/include/dm/uclass-id.h
1304@@ -63,6 +63,7 @@ enum uclass_id {
1305 UCLASS_ETH_PHY, /* Ethernet PHY device */
1306 UCLASS_EXTCON, /* External Connector Class */
1307 UCLASS_FFA, /* Arm Firmware Framework for Armv8-A */
1308+ UCLASS_FFA_EMUL, /* sandbox FF-A device emulator */
1309 UCLASS_FIRMWARE, /* Firmware */
1310 UCLASS_FPGA, /* FPGA device */
1311 UCLASS_FUZZING_ENGINE, /* Fuzzing engine */