blob: 617aaf77e2676c7198aa17f7d7b5ad77bfd716ed [file] [log] [blame]
Patrick Williams92b42cb2022-09-03 06:53:57 -05001From 968c86e8a6ed3e9e6621f0ae44977b5b13d90bfd Mon Sep 17 00:00:00 2001
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
3Date: Tue, 16 Nov 2021 12:34:52 +0000
Patrick Williams92b42cb2022-09-03 06:53:57 -05004Subject: [PATCH 06/24] arm_ffa: introducing Arm FF-A low-level driver
Brad Bishopbec4ebc2022-08-03 09:55:16 -04005
6This driver implements Arm Firmware Framework for Armv8-A on u-boot
7
8The Firmware Framework for Arm A-profile processors (FF-A)
9describes interfaces (ABIs) that standardize communication
10between the Secure World and Normal World leveraging TrustZone
11technology.
12
13This driver is based on FF-A specification v1.0 and uses SMC32
14calling convention.
15
16FF-A specification:
17
18https://developer.arm.com/documentation/den0077/a/?lang=en
19
20The driver provides helper FF-A interfaces for user layers.
21These helper functions allow clients to pass data and select the
22FF-A function to use for the communication with secure world.
23
24Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
25Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
26---
27 MAINTAINERS | 8 +
28 arch/arm/cpu/armv8/smccc-call.S | 27 +
29 arch/arm/lib/asm-offsets.c | 6 +
30 common/board_r.c | 6 +
31 drivers/Kconfig | 2 +
32 drivers/Makefile | 1 +
33 drivers/arm-ffa/Kconfig | 26 +
34 drivers/arm-ffa/Makefile | 3 +
35 drivers/arm-ffa/arm-ffa-uclass.c | 67 ++
36 drivers/arm-ffa/arm_ffa_prv.h | 199 ++++
37 drivers/arm-ffa/core.c | 1484 ++++++++++++++++++++++++++++++
38 include/arm_ffa.h | 191 ++++
39 include/arm_ffa_helper.h | 45 +
40 include/dm/uclass-id.h | 1 +
41 include/linux/arm-smccc.h | 28 +-
42 lib/Kconfig | 1 +
43 lib/Makefile | 1 +
44 lib/arm-ffa/Kconfig | 6 +
45 lib/arm-ffa/Makefile | 8 +
46 lib/arm-ffa/arm_ffa_helper.c | 188 ++++
47 lib/efi_loader/efi_boottime.c | 17 +
48 21 files changed, 2314 insertions(+), 1 deletion(-)
49 create mode 100644 drivers/arm-ffa/Kconfig
50 create mode 100644 drivers/arm-ffa/Makefile
51 create mode 100644 drivers/arm-ffa/arm-ffa-uclass.c
52 create mode 100644 drivers/arm-ffa/arm_ffa_prv.h
53 create mode 100644 drivers/arm-ffa/core.c
54 create mode 100644 include/arm_ffa.h
55 create mode 100644 include/arm_ffa_helper.h
56 create mode 100644 lib/arm-ffa/Kconfig
57 create mode 100644 lib/arm-ffa/Makefile
58 create mode 100644 lib/arm-ffa/arm_ffa_helper.c
59
60diff --git a/MAINTAINERS b/MAINTAINERS
Patrick Williams92b42cb2022-09-03 06:53:57 -050061index 7f27ff4c20fc..d29d7e040764 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -040062--- a/MAINTAINERS
63+++ b/MAINTAINERS
Patrick Williams92b42cb2022-09-03 06:53:57 -050064@@ -244,6 +244,14 @@ F: board/CZ.NIC/
Brad Bishopbec4ebc2022-08-03 09:55:16 -040065 F: configs/turris_*_defconfig
66 F: include/configs/turris_*.h
67
68+ARM FF-A
69+M: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
70+S: Maintained
71+F: drivers/arm-ffa/
72+F: include/arm_ffa.h
73+F: include/arm_ffa_helper.h
74+F: lib/arm-ffa/
75+
76 ARM FREESCALE IMX
77 M: Stefano Babic <sbabic@denx.de>
78 M: Fabio Estevam <festevam@gmail.com>
79diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
80index dc92b28777c3..ffc39c9fefa2 100644
81--- a/arch/arm/cpu/armv8/smccc-call.S
82+++ b/arch/arm/cpu/armv8/smccc-call.S
83@@ -1,6 +1,8 @@
84 /* SPDX-License-Identifier: GPL-2.0 */
85 /*
86 * Copyright (c) 2015, Linaro Limited
87+ * (C) Copyright 2021 ARM Limited
88+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
89 */
90 #include <linux/linkage.h>
91 #include <linux/arm-smccc.h>
92@@ -45,3 +47,28 @@ ENDPROC(__arm_smccc_smc)
93 ENTRY(__arm_smccc_hvc)
94 SMCCC hvc
95 ENDPROC(__arm_smccc_hvc)
96+
97+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
98+
99+ .macro FFASMCCC instr
100+ .cfi_startproc
101+ \instr #0
102+ ldr x9, [sp]
103+ stp x0, x1, [x9, #ARM_SMCCC_RES_X0_OFFS]
104+ stp x2, x3, [x9, #ARM_SMCCC_RES_X2_OFFS]
105+ stp x4, x5, [x9, #ARM_SMCCC_RES_X4_OFFS]
106+ stp x6, x7, [x9, #ARM_SMCCC_RES_X6_OFFS]
107+ ret
108+ .cfi_endproc
109+ .endm
110+
111+/*
112+ * void arm_ffa_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
113+ * unsigned long a3, unsigned long a4, unsigned long a5,
114+ * unsigned long a6, unsigned long a7, struct arm_smccc_res *res)
115+ */
116+ENTRY(__arm_ffa_smccc_smc)
117+ FFASMCCC smc
118+ENDPROC(__arm_ffa_smccc_smc)
119+
120+#endif
121diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
122index 22fd541f9a28..45eca83a473c 100644
123--- a/arch/arm/lib/asm-offsets.c
124+++ b/arch/arm/lib/asm-offsets.c
125@@ -9,6 +9,8 @@
126 * generate asm statements containing #defines,
127 * compile this file to assembler, and then extract the
128 * #defines from the assembly-language output.
129+ *
130+ * (C) Copyright 2021 ARM Limited
131 */
132
133 #include <common.h>
134@@ -115,6 +117,10 @@ int main(void)
135 #ifdef CONFIG_ARM_SMCCC
136 DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
137 DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
138+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
139+ DEFINE(ARM_SMCCC_RES_X4_OFFS, offsetof(struct arm_smccc_res, a4));
140+ DEFINE(ARM_SMCCC_RES_X6_OFFS, offsetof(struct arm_smccc_res, a6));
141+#endif
142 DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
143 DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
144 #endif
145diff --git a/common/board_r.c b/common/board_r.c
Patrick Williams92b42cb2022-09-03 06:53:57 -0500146index 6f4aca2077d6..412a0ea9fac3 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400147--- a/common/board_r.c
148+++ b/common/board_r.c
Patrick Williams92b42cb2022-09-03 06:53:57 -0500149@@ -62,6 +62,9 @@
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400150 #include <asm-generic/gpio.h>
151 #include <efi_loader.h>
Patrick Williams92b42cb2022-09-03 06:53:57 -0500152 #include <relocate.h>
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400153+#ifdef CONFIG_ARM_FFA_TRANSPORT
154+#include <arm_ffa_helper.h>
155+#endif
156
157 DECLARE_GLOBAL_DATA_PTR;
158
Patrick Williams92b42cb2022-09-03 06:53:57 -0500159@@ -779,6 +782,9 @@ static init_fnc_t init_sequence_r[] = {
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400160 INIT_FUNC_WATCHDOG_RESET
161 initr_net,
162 #endif
163+#ifdef CONFIG_ARM_FFA_TRANSPORT
164+ ffa_helper_init_device,
165+#endif
166 #ifdef CONFIG_POST
167 initr_post,
168 #endif
169diff --git a/drivers/Kconfig b/drivers/Kconfig
170index b26ca8cf70c9..e83c23789d1b 100644
171--- a/drivers/Kconfig
172+++ b/drivers/Kconfig
173@@ -6,6 +6,8 @@ source "drivers/core/Kconfig"
174
175 source "drivers/adc/Kconfig"
176
177+source "drivers/arm-ffa/Kconfig"
178+
179 source "drivers/ata/Kconfig"
180
181 source "drivers/axi/Kconfig"
182diff --git a/drivers/Makefile b/drivers/Makefile
Patrick Williams92b42cb2022-09-03 06:53:57 -0500183index 67c8af74424e..1be687b55d13 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400184--- a/drivers/Makefile
185+++ b/drivers/Makefile
Patrick Williams92b42cb2022-09-03 06:53:57 -0500186@@ -109,6 +109,7 @@ obj-y += iommu/
Brad Bishopbec4ebc2022-08-03 09:55:16 -0400187 obj-y += smem/
188 obj-y += thermal/
189 obj-$(CONFIG_TEE) += tee/
190+obj-$(CONFIG_ARM_FFA_TRANSPORT) += arm-ffa/
191 obj-y += axi/
192 obj-y += ufs/
193 obj-$(CONFIG_W1) += w1/
194diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
195new file mode 100644
196index 000000000000..d71444c1fa90
197--- /dev/null
198+++ b/drivers/arm-ffa/Kconfig
199@@ -0,0 +1,26 @@
200+# SPDX-License-Identifier: GPL-2.0
201+
202+config ARM_FFA_TRANSPORT
203+ bool "Enable Arm Firmware Framework for Armv8-A driver"
204+ depends on DM && ARM64
205+ select ARM_SMCCC
206+ select LIB_UUID
207+ select ARM_FFA_TRANSPORT_HELPERS
208+ select CMD_ARMFFA
209+ help
210+ The Firmware Framework for Arm A-profile processors (FF-A)
211+ describes interfaces (ABIs) that standardize communication
212+ between the Secure World and Normal World leveraging TrustZone
213+ technology.
214+
215+ This driver is based on FF-A specification v1.0 and uses SMC32
216+ calling convention.
217+
218+ FF-A specification:
219+
220+ https://developer.arm.com/documentation/den0077/a/?lang=en
221+
222+ In u-boot FF-A design, the Secure World is considered as one
223+ entity to communicate with. FF-A communication is handled by
224+ one device and one instance. This device takes care of
225+ all the interactions between Normal world and Secure World.
226diff --git a/drivers/arm-ffa/Makefile b/drivers/arm-ffa/Makefile
227new file mode 100644
228index 000000000000..9fb5bea52299
229--- /dev/null
230+++ b/drivers/arm-ffa/Makefile
231@@ -0,0 +1,3 @@
232+# SPDX-License-Identifier: GPL-2.0+
233+
234+obj-y += arm-ffa-uclass.o core.o
235diff --git a/drivers/arm-ffa/arm-ffa-uclass.c b/drivers/arm-ffa/arm-ffa-uclass.c
236new file mode 100644
237index 000000000000..43f6066281fe
238--- /dev/null
239+++ b/drivers/arm-ffa/arm-ffa-uclass.c
240@@ -0,0 +1,67 @@
241+// SPDX-License-Identifier: GPL-2.0+
242+/*
243+ * (C) Copyright 2021 ARM Limited
244+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
245+ */
246+
247+#include <common.h>
248+#include <dm.h>
249+#include <arm_ffa.h>
250+#include <errno.h>
251+#include <log.h>
252+#include <asm/global_data.h>
253+
254+DECLARE_GLOBAL_DATA_PTR;
255+
256+UCLASS_DRIVER(ffa) = {
257+ .name = "ffa",
258+ .id = UCLASS_FFA,
259+};
260+
261+/**
262+ * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher
263+ * @func_id: The FF-A function to be used
264+ * @func_data: Pointer to the FF-A function arguments
265+ * container structure. This also includes
266+ * pointers to the returned data needed by
267+ * clients.
268+ *
269+ * This runtime function passes the FF-A function ID and its arguments to
270+ * the FF-A driver dispatcher.
271+ * This function is called by the FF-A helper functions.
272+ *
273+ * Return:
274+ *
275+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
276+ */
277+int __ffa_runtime ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *func_data)
278+{
279+ if (!ffa_device_get_ops()->invoke_func)
280+ return -EINVAL;
281+
282+ return ffa_device_get_ops()->invoke_func(func_id, func_data);
283+}
284+
285+/**
286+ * ffa_init_device - probes the arm_ffa device
287+ *
288+ * This boot time function makes sure the arm_ffa device is probed
289+ * and ready for use.
290+ * This function is called automatically at initcalls
291+ * level (after u-boot relocation).
292+ *
293+ * Arm FF-A transport is implemented through a single u-boot
294+ * device (arm_ffa). So, there is only one device belonging to UCLASS_FFA.
295+ * All FF-A clients should use the arm_ffa device to use the FF-A
296+ * transport.
297+ *
298+ * Return:
299+ *
300+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
301+ */
302+int ffa_init_device(void)
303+{
304+ ffa_dbg("[%s]", __func__);
305+
306+ return ffa_get_device();
307+}
308diff --git a/drivers/arm-ffa/arm_ffa_prv.h b/drivers/arm-ffa/arm_ffa_prv.h
309new file mode 100644
310index 000000000000..38ea4ba83efc
311--- /dev/null
312+++ b/drivers/arm-ffa/arm_ffa_prv.h
313@@ -0,0 +1,199 @@
314+/* SPDX-License-Identifier: GPL-2.0+ */
315+/*
316+ * (C) Copyright 2021 ARM Limited
317+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
318+ */
319+
320+#ifndef __ARM_FFA_PRV_H
321+#define __ARM_FFA_PRV_H
322+
323+#include <arm_ffa.h>
324+#include <linux/bitfield.h>
325+#include <linux/bitops.h>
326+
327+/*
328+ * This header is private. It is exclusively used by the FF-A driver
329+ */
330+
331+/* FF-A driver version definitions */
332+
333+#define MAJOR_VERSION_MASK GENMASK(30, 16)
334+#define MINOR_VERSION_MASK GENMASK(15, 0)
335+#define GET_FFA_MAJOR_VERSION(x) \
336+ ((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
337+#define GET_FFA_MINOR_VERSION(x) \
338+ ((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
339+#define PACK_VERSION_INFO(major, minor) \
340+ (FIELD_PREP(MAJOR_VERSION_MASK, (major)) | \
341+ FIELD_PREP(MINOR_VERSION_MASK, (minor)))
342+
343+#define FFA_MAJOR_VERSION (1)
344+#define FFA_MINOR_VERSION (0)
345+#define FFA_VERSION_1_0 \
346+ PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
347+
348+/* Endpoint ID mask (u-boot endpoint ID) */
349+
350+#define GET_SELF_ENDPOINT_ID_MASK GENMASK(15, 0)
351+#define GET_SELF_ENDPOINT_ID(x) \
352+ ((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
353+
354+#define PREP_SELF_ENDPOINT_ID_MASK GENMASK(31, 16)
355+#define PREP_SELF_ENDPOINT_ID(x) \
356+ ((u16)(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x))))
357+
358+/* Partition endpoint ID mask (partition with which u-boot communicates with) */
359+
360+#define PREP_PART_ENDPOINT_ID_MASK GENMASK(15, 0)
361+#define PREP_PART_ENDPOINT_ID(x) \
362+ ((u16)(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x))))
363+
364+/* The FF-A SMC function prototype definition */
365+
366+typedef void (*invoke_ffa_fn_t)(unsigned long a0, unsigned long a1,
367+ unsigned long a2, unsigned long a3, unsigned long a4,
368+ unsigned long a5, unsigned long a6, unsigned long a7,
369+ struct arm_smccc_res *res);
370+
371+/**
372+ * enum ffa_conduit - Arm FF-A conduits supported by the Arm FF-A driver
373+ * Currently only SMC32 is supported.
374+ */
375+enum ffa_conduit {
376+ FFA_CONDUIT_SMC = 0,
377+};
378+
379+/**
380+ * FFA_DECLARE_ARGS - FF-A functions local variables
381+ * @a0-a7: local variables used to set registers x0-x7
382+ * @res: the structure hosting the FF-A function return data
383+ *
384+ * A helper macro for declaring local variables for the FF-A functions arguments.
385+ * The x0-x7 registers are used to exchange data with the secure world.
386+ * But, only the bottom 32-bit of thes registers contains the data.
387+ */
388+#define FFA_DECLARE_ARGS \
389+ unsigned long a0 = 0; \
390+ unsigned long a1 = 0; \
391+ unsigned long a2 = 0; \
392+ unsigned long a3 = 0; \
393+ unsigned long a4 = 0; \
394+ unsigned long a5 = 0; \
395+ unsigned long a6 = 0; \
396+ unsigned long a7 = 0; \
397+ struct arm_smccc_res res = {0}
398+
399+/* FF-A error codes */
400+#define FFA_ERR_STAT_NOT_SUPPORTED (-1)
401+#define FFA_ERR_STAT_INVALID_PARAMETERS (-2)
402+#define FFA_ERR_STAT_NO_MEMORY (-3)
403+#define FFA_ERR_STAT_BUSY (-4)
404+#define FFA_ERR_STAT_INTERRUPTED (-5)
405+#define FFA_ERR_STAT_DENIED (-6)
406+#define FFA_ERR_STAT_RETRY (-7)
407+#define FFA_ERR_STAT_ABORTED (-8)
408+
409+/**
410+ * struct ffa_features_desc - FF-A functions features
411+ * @func_id: FF-A function
412+ * @field1: features read from register w2
413+ * @field2: features read from register w3
414+ *
415+ * Data structure describing the features of the FF-A functions queried by
416+ * FFA_FEATURES
417+ */
418+struct ffa_features_desc {
419+ u32 func_id;
420+ u32 field1;
421+ u32 field2;
422+};
423+
424+/**
425+ * enum ffa_rxtx_buf_sizes - minimum sizes supported
426+ * for the RX/TX buffers
427+ */
428+enum ffa_rxtx_buf_sizes {
429+ RXTX_4K,
430+ RXTX_64K,
431+ RXTX_16K
432+};
433+
434+/*
435+ * Number of the FF-A interfaces features descriptors
436+ * currently only FFA_RXTX_MAP descriptor is supported
437+ */
438+#define FFA_FEATURE_DESC_CNT (1)
439+
440+/**
441+ * struct ffa_pdata - platform data for the arm_ffa device
442+ * @conduit: The FF-A conduit used
443+ *
444+ * Platform data structure read from the device tree
445+ */
446+struct ffa_pdata {
447+ enum ffa_conduit conduit;
448+};
449+
450+/**
451+ * struct ffa_rxtxpair - structure hosting the RX/TX buffers physical addresses
452+ * @rxbuf: physical address of the RX buffer
453+ * @txbuf: physical address of the TX buffer
454+ *
455+ * Data structure hosting the physical addresses of the mapped RX/TX buffers
456+ * These physical address are used by the FF-A functions that use the RX/TX buffers
457+ */
458+struct ffa_rxtxpair {
459+ u64 rxbuf; /* physical address */
460+ u64 txbuf; /* physical address */
461+};
462+
463+/**
464+ * struct ffa_partition_desc - the secure partition descriptor
465+ * @info: partition information
466+ * @UUID: UUID
467+ *
468+ * Each partition has its descriptor containing the partitions information and the UUID
469+ */
470+struct ffa_partition_desc {
471+ struct ffa_partition_info info;
472+ union ffa_partition_uuid UUID;
473+};
474+
475+/**
476+ * struct ffa_partitions - descriptors for all secure partitions
477+ * @count: The number of partitions descriptors
478+ * @descs The partitions descriptors table
479+ *
480+ * This data structure contains the partitions descriptors table
481+ */
482+struct ffa_partitions {
483+ u32 count;
484+ struct ffa_partition_desc *descs; /* virtual address */
485+};
486+
487+/**
488+ * struct ffa_prvdata - the driver private data structure
489+ *
490+ * @dev: The arm_ffa device under u-boot driver model
491+ * @fwk_version: FF-A framework version
492+ * @id: u-boot endpoint ID
493+ * @partitions: The partitions descriptors structure
494+ * @pair: The RX/TX buffers pair
495+ * @conduit: The selected conduit
496+ * @invoke_ffa_fn: The function executing the FF-A function
497+ * @features: Table of the FF-A functions having features
498+ *
499+ * The driver data structure hosting all resident data.
500+ */
501+struct ffa_prvdata {
502+ struct udevice *dev;
503+ u32 fwk_version;
504+ u16 id;
505+ struct ffa_partitions partitions;
506+ struct ffa_rxtxpair pair;
507+ enum ffa_conduit conduit;
508+ invoke_ffa_fn_t invoke_ffa_fn;
509+ struct ffa_features_desc features[FFA_FEATURE_DESC_CNT];
510+};
511+
512+#endif
513diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c
514new file mode 100644
515index 000000000000..98e2d2fa1767
516--- /dev/null
517+++ b/drivers/arm-ffa/core.c
518@@ -0,0 +1,1484 @@
519+// SPDX-License-Identifier: GPL-2.0+
520+/*
521+ * (C) Copyright 2021 ARM Limited
522+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
523+ */
524+
525+#include "arm_ffa_prv.h"
526+#include <asm/global_data.h>
527+#include <asm/io.h>
528+#include <common.h>
529+#include <dm.h>
530+#include <fdtdec.h>
531+#include <linux/errno.h>
532+#include <linux/sizes.h>
533+#include <log.h>
534+#include <malloc.h>
535+#include <mapmem.h>
536+#include <string.h>
537+
538+DECLARE_GLOBAL_DATA_PTR;
539+
540+/**
541+ * The device private data structure containing all the resident
542+ * data read from secure world
543+ */
544+struct ffa_prvdata __ffa_runtime_data ffa_priv_data = {0};
545+
546+/*
547+ * Driver functions
548+ */
549+
550+/**
551+ * ffa_get_device - probes the arm_ffa device
552+ *
553+ * This boot time function makes sure the arm_ffa device is probed
554+ * and ready for use. This is done using uclass_get_device.
555+ * The arm_ffa driver belongs to UCLASS_FFA.
556+ * This function should be called before using the driver.
557+ *
558+ * Arm FF-A transport is implemented through a single u-boot
559+ * device (arm_ffa). So, there is only one device belonging to UCLASS_FFA.
560+ * All FF-A clients should use the arm_ffa device to use the FF-A
561+ * transport.
562+ *
563+ * Return:
564+ *
565+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
566+ */
567+int ffa_get_device(void)
568+{
569+ int ret;
570+ int devnum = 0;
571+
572+ ffa_dbg("[%s]", __func__);
573+
574+ if (ffa_priv_data.dev)
575+ return FFA_ERR_STAT_SUCCESS;
576+
577+ /*
578+ * searching and probing the device
579+ */
580+ ret = uclass_get_device(UCLASS_FFA, devnum, &ffa_priv_data.dev);
581+ if (ret) {
582+ ffa_err("can not find the device");
583+ ffa_priv_data.dev = NULL;
584+ return -ENODEV;
585+ }
586+
587+ return FFA_ERR_STAT_SUCCESS;
588+}
589+
590+/**
591+ * ffa_get_version - FFA_VERSION handler function
592+ *
593+ * This is the boot time function that implements FFA_VERSION FF-A function
594+ * to get from the secure world the FF-A framework version
595+ *
596+ * Return:
597+ *
598+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
599+ */
600+static int ffa_get_version(void)
601+{
602+ u16 major, minor;
603+
604+ FFA_DECLARE_ARGS;
605+
606+ ffa_dbg("[%s]", __func__);
607+
608+ if (!ffa_priv_data.invoke_ffa_fn)
609+ panic("[FFA] no private data found\n");
610+
611+ a0 = FFA_VERSION;
612+ a1 = FFA_VERSION_1_0;
613+ ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
614+
615+ if (res.a0 == FFA_ERR_STAT_NOT_SUPPORTED) {
616+ ffa_err("A Firmware Framework implementation does not exist");
617+ return -EOPNOTSUPP;
618+ }
619+
620+ major = GET_FFA_MAJOR_VERSION(res.a0);
621+ minor = GET_FFA_MINOR_VERSION(res.a0);
622+
623+ ffa_info("FF-A driver %d.%d\nFF-A framework %d.%d",
624+ FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor);
625+
626+ if ((major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION)) {
627+ ffa_info("Versions are compatible ");
628+
629+ ffa_priv_data.fwk_version = res.a0;
630+
631+ return FFA_ERR_STAT_SUCCESS;
632+ }
633+
634+ ffa_info("Versions are incompatible ");
635+ return -EPROTONOSUPPORT;
636+}
637+
638+/**
639+ * ffa_get_endpoint_id - FFA_ID_GET handler function
640+ *
641+ * This is the boot time function that implements FFA_ID_GET FF-A function
642+ * to get from the secure world u-boot endpoint ID
643+ *
644+ * Return:
645+ *
646+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
647+ */
648+static int ffa_get_endpoint_id(void)
649+{
650+ FFA_DECLARE_ARGS;
651+
652+ ffa_dbg("[%s]", __func__);
653+
654+ if (!ffa_priv_data.invoke_ffa_fn)
655+ panic("[FFA] no private data found\n");
656+
657+ a0 = FFA_ID_GET;
658+
659+ ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
660+
661+ switch (res.a0) {
662+ case FFA_ERROR:
663+ {
664+ if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
665+ ffa_err("This function is not implemented at this FF-A instance");
666+ return -EOPNOTSUPP;
667+ }
668+
669+ ffa_err("Undefined error code (%d)", ((int)res.a2));
670+ return -EINVAL;
671+ }
672+ case FFA_SUCCESS:
673+ {
674+ ffa_priv_data.id = GET_SELF_ENDPOINT_ID(res.a2);
675+ ffa_info("endpoint ID is %u", ffa_priv_data.id);
676+
677+ return FFA_ERR_STAT_SUCCESS;
678+ }
679+ default:
680+ {
681+ ffa_err("Undefined response function (0x%lx)", res.a0);
682+ return -EINVAL;
683+ }
684+ }
685+}
686+
687+/**
688+ * ffa_get_features_desc - returns the features descriptor of the specified
689+ * FF-A function
690+ * @func_id: the FF-A function which the features are to be retrieved
691+ *
692+ * This is a boot time function that searches the features descriptor of the
693+ * specified FF-A function
694+ *
695+ * Return:
696+ *
697+ * When found, the address of the features descriptor is returned. Otherwise, NULL.
698+ */
699+static struct ffa_features_desc *ffa_get_features_desc(u32 func_id)
700+{
701+ u32 desc_idx;
702+
703+ /*
704+ * search for the descriptor of the selected FF-A interface
705+ */
706+ for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
707+ if (ffa_priv_data.features[desc_idx].func_id == func_id)
708+ return &ffa_priv_data.features[desc_idx];
709+
710+ return NULL;
711+}
712+
713+/**
714+ * ffa_get_rxtx_map_features - FFA_FEATURES handler function with FFA_RXTX_MAP
715+ * argument
716+ *
717+ * This is the boot time function that implements FFA_FEATURES FF-A function
718+ * to retrieve the FFA_RXTX_MAP features
719+ *
720+ * Return:
721+ *
722+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
723+ */
724+static int ffa_get_rxtx_map_features(void)
725+{
726+ FFA_DECLARE_ARGS;
727+
728+ ffa_dbg("[%s]", __func__);
729+
730+ if (!ffa_priv_data.invoke_ffa_fn)
731+ panic("[FFA] no private data found\n");
732+
733+ a0 = FFA_FEATURES;
734+ a1 = FFA_RXTX_MAP;
735+
736+ ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
737+
738+ switch (res.a0) {
739+ case FFA_ERROR:
740+ {
741+ if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED) {
742+ ffa_err("FFA_RXTX_MAP is not implemented at this FF-A instance");
743+ return -EOPNOTSUPP;
744+ }
745+
746+ ffa_err("Undefined error code (%d)", ((int)res.a2));
747+ return -EINVAL;
748+ }
749+ case FFA_SUCCESS:
750+ {
751+ u32 desc_idx;
752+
753+ /*
754+ * search for an empty descriptor
755+ */
756+ for (desc_idx = 0; desc_idx < FFA_FEATURE_DESC_CNT ; desc_idx++)
757+ if (!ffa_priv_data.features[desc_idx].func_id) {
758+ /*
759+ * populate the descriptor with
760+ * the interface features data
761+ */
762+ ffa_priv_data.features[desc_idx].func_id =
763+ FFA_RXTX_MAP;
764+ ffa_priv_data.features[desc_idx].field1 =
765+ res.a2;
766+
767+ ffa_info("FFA_RXTX_MAP features data 0x%lx",
768+ res.a2);
769+
770+ return FFA_ERR_STAT_SUCCESS;
771+ }
772+
773+ ffa_err("Cannot save FFA_RXTX_MAP features data. Descriptors table full");
774+ return -ENOBUFS;
775+ }
776+ default:
777+ {
778+ ffa_err("Undefined response function (0x%lx)",
779+ res.a0);
780+ return -EINVAL;
781+ }
782+ }
783+}
784+
785+/**
786+ * ffa_get_rxtx_buffers_pages_cnt - reads from the features data descriptors
787+ * the minimum number of pages in each of the RX/TX
788+ * buffers
789+ * @buf_4k_pages: Pointer to the minimum number of pages
790+ *
791+ * This is the boot time function that returns the minimum number of pages
792+ * in each of the RX/TX buffers
793+ *
794+ * Return:
795+ *
796+ * buf_4k_pages points to the returned number of pages
797+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
798+ */
799+static int ffa_get_rxtx_buffers_pages_cnt(size_t *buf_4k_pages)
800+{
801+ struct ffa_features_desc *desc = NULL;
802+
803+ ffa_dbg("[%s]", __func__);
804+
805+ if (!buf_4k_pages)
806+ return -EINVAL;
807+
808+ desc = ffa_get_features_desc(FFA_RXTX_MAP);
809+ if (!desc)
810+ return -EINVAL;
811+
812+ ffa_dbg("FFA_RXTX_MAP descriptor found");
813+
814+ switch (desc->field1) {
815+ case RXTX_4K:
816+ *buf_4k_pages = 1;
817+ break;
818+ case RXTX_16K:
819+ *buf_4k_pages = 4;
820+ break;
821+ case RXTX_64K:
822+ *buf_4k_pages = 16;
823+ break;
824+ default:
825+ ffa_err("RX/TX buffer size not supported");
826+ return -EINVAL;
827+ }
828+
829+ return FFA_ERR_STAT_SUCCESS;
830+}
831+
832+/**
833+ * ffa_free_rxtx_buffers - frees the RX/TX buffers
834+ * @buf_4k_pages: the minimum number of pages in each of the RX/TX
835+ * buffers
836+ *
837+ * This is the boot time function used to free the RX/TX buffers
838+ *
839+ * Return:
840+ *
841+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
842+ */
843+static int ffa_free_rxtx_buffers(size_t buf_4k_pages)
844+{
845+ efi_status_t free_rxbuf_ret, free_txbuf_ret;
846+
847+ ffa_info("Freeing RX/TX buffers");
848+
849+ free_rxbuf_ret = efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
850+ free_txbuf_ret = efi_free_pages(ffa_priv_data.pair.txbuf, buf_4k_pages);
851+
852+ if (free_rxbuf_ret != EFI_SUCCESS || free_txbuf_ret != EFI_SUCCESS) {
853+ ffa_err("Failed to free RX/TX buffers (rx: %lu , tx: %lu)",
854+ free_rxbuf_ret,
855+ free_txbuf_ret);
856+ return -EINVAL;
857+ }
858+
859+ return FFA_ERR_STAT_SUCCESS;
860+}
861+
862+/**
863+ * ffa_alloc_rxtx_buffers - allocates the RX/TX buffers
864+ * @buf_4k_pages: the minimum number of pages in each of the RX/TX
865+ * buffers
866+ *
867+ * This is the boot time function used by ffa_map_rxtx_buffers to allocate
868+ * the RX/TX buffers before mapping them
869+ *
870+ * Return:
871+ *
872+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
873+ */
874+static int ffa_alloc_rxtx_buffers(size_t buf_4k_pages)
875+{
876+ ffa_dbg("[%s]", __func__);
877+
878+#if CONFIG_IS_ENABLED(EFI_LOADER)
879+
880+ efi_status_t efi_ret;
881+ void *virt_txbuf;
882+ void *virt_rxbuf;
883+
884+ ffa_info("Using %lu 4KB page(s) for RX/TX buffers size",
885+ buf_4k_pages);
886+
887+ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
888+ EFI_BOOT_SERVICES_DATA,
889+ buf_4k_pages,
890+ &ffa_priv_data.pair.rxbuf);
891+
892+ if (efi_ret != EFI_SUCCESS) {
893+ ffa_priv_data.pair.rxbuf = 0;
894+ ffa_err("Failure to allocate RX buffer (EFI error: 0x%lx)",
895+ efi_ret);
896+
897+ return -ENOBUFS;
898+ }
899+
900+ ffa_info("RX buffer at phys 0x%llx",
901+ ffa_priv_data.pair.rxbuf);
902+
903+ /*
904+ * convert the RX buffer physical address to virtual address
905+ */
906+ virt_rxbuf = (void *)map_sysmem((phys_addr_t)ffa_priv_data.pair.rxbuf, 0);
907+
908+ /*
909+ * make sure the buffer is clean before use
910+ */
911+ memset(virt_rxbuf, 0, buf_4k_pages * SZ_4K);
912+
913+ unmap_sysmem(virt_rxbuf);
914+
915+ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
916+ EFI_RUNTIME_SERVICES_DATA,
917+ buf_4k_pages,
918+ &ffa_priv_data.pair.txbuf);
919+
920+ if (efi_ret != EFI_SUCCESS) {
921+ ffa_dbg("FFA_RXTX_MAP: freeing RX buffer");
922+ efi_free_pages(ffa_priv_data.pair.rxbuf, buf_4k_pages);
923+ ffa_priv_data.pair.rxbuf = 0;
924+ ffa_priv_data.pair.txbuf = 0;
925+ ffa_err("Failure to allocate the TX buffer (EFI error: 0x%lx)"
926+ , efi_ret);
927+
928+ return -ENOBUFS;
929+ }
930+
931+ ffa_info("TX buffer at phys 0x%llx",
932+ ffa_priv_data.pair.txbuf);
933+
934+ /*
935+ * convert the TX buffer physical address to virtual address
936+ */
937+ virt_txbuf = (void *)map_sysmem((phys_addr_t)ffa_priv_data.pair.txbuf, 0);
938+
939+ /*
940+ * make sure the buffer is clean before use
941+ */
942+ memset(virt_txbuf, 0, buf_4k_pages * SZ_4K);
943+
944+ unmap_sysmem(virt_txbuf);
945+
946+ return FFA_ERR_STAT_SUCCESS;
947+
948+#else
949+ return -ENOBUFS;
950+#endif
951+}
952+
953+/**
954+ * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function
955+ * @buf_4k_pages: the minimum number of pages in each of the RX/TX
956+ * buffers
957+ *
958+ * This is the boot time function that implements FFA_RXTX_MAP FF-A function
959+ * to map the RX/TX buffers
960+ *
961+ * Return:
962+ *
963+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
964+ */
965+static int ffa_map_rxtx_buffers(size_t buf_4k_pages)
966+{
967+ int ret;
968+
969+ FFA_DECLARE_ARGS;
970+
971+ ffa_dbg("[%s]", __func__);
972+
973+ if (!ffa_priv_data.invoke_ffa_fn)
974+ panic("[FFA] no private data found\n");
975+
976+ ret = ffa_alloc_rxtx_buffers(buf_4k_pages);
977+ if (ret != FFA_ERR_STAT_SUCCESS)
978+ return ret;
979+
980+ a0 = FFA_RXTX_MAP;
981+ a1 = ffa_priv_data.pair.txbuf;
982+ a2 = ffa_priv_data.pair.rxbuf;
983+ a3 = buf_4k_pages;
984+
985+ ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
986+
987+ switch (res.a0) {
988+ case FFA_ERROR:
989+ {
990+ switch (((int)res.a2)) {
991+ case FFA_ERR_STAT_INVALID_PARAMETERS:
992+ ffa_err("One or more fields in input parameters is incorrectly encoded");
993+ ret = -EPERM;
994+ break;
995+ case FFA_ERR_STAT_NO_MEMORY:
996+ ffa_err("Not enough memory");
997+ ret = -ENOMEM;
998+ break;
999+ case FFA_ERR_STAT_DENIED:
1000+ ffa_err("Buffer pair already registered");
1001+ ret = -EACCES;
1002+ break;
1003+ case FFA_ERR_STAT_NOT_SUPPORTED:
1004+ ffa_err("This function is not implemented at this FF-A instance");
1005+ ret = -EOPNOTSUPP;
1006+ break;
1007+ default:
1008+ ffa_err("Undefined error (%d)",
1009+ ((int)res.a2));
1010+ ret = -EINVAL;
1011+ }
1012+ break;
1013+ }
1014+ case FFA_SUCCESS:
1015+ ffa_info("RX/TX buffers mapped");
1016+ return FFA_ERR_STAT_SUCCESS;
1017+ default:
1018+ ffa_err("Undefined response function (0x%lx)",
1019+ res.a0);
1020+ ret = -EINVAL;
1021+ }
1022+
1023+ ffa_free_rxtx_buffers(buf_4k_pages);
1024+
1025+ return ret;
1026+}
1027+
1028+/**
1029+ * ffa_unmap_rxtx_buffers - FFA_RXTX_UNMAP handler function
1030+ *
1031+ * This is the boot time function that implements FFA_RXTX_UNMAP FF-A function
1032+ * to unmap the RX/TX buffers
1033+ *
1034+ * Return:
1035+ *
1036+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
1037+ */
1038+static int ffa_unmap_rxtx_buffers(void)
1039+{
1040+ FFA_DECLARE_ARGS;
1041+
1042+ ffa_dbg("[%s]", __func__);
1043+
1044+ if (!ffa_priv_data.invoke_ffa_fn)
1045+ panic("[FFA] no private data found\n");
1046+
1047+ a0 = FFA_RXTX_UNMAP;
1048+ a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id);
1049+
1050+ ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
1051+
1052+ switch (res.a0) {
1053+ case FFA_ERROR:
1054+ {
1055+ if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
1056+ panic("[FFA] FFA_RXTX_UNMAP is not implemented at this FF-A instance\n");
1057+ else if (((int)res.a2) == FFA_ERR_STAT_INVALID_PARAMETERS)
1058+ panic("[FFA] There is no buffer pair registered on behalf of the caller\n");
1059+ else
1060+ panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
1061+ }
1062+ case FFA_SUCCESS:
1063+ {
1064+ size_t buf_4k_pages = 0;
1065+ int ret;
1066+
1067+ ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
1068+ if (ret != FFA_ERR_STAT_SUCCESS)
1069+ panic("[FFA] RX/TX buffers unmapped but failure in getting pages count\n");
1070+
1071+ ret = ffa_free_rxtx_buffers(buf_4k_pages);
1072+ if (ret != FFA_ERR_STAT_SUCCESS)
1073+ panic("[FFA] RX/TX buffers unmapped but failure in freeing the memory\n");
1074+
1075+ ffa_info("RX/TX buffers unmapped and memory freed");
1076+
1077+ return FFA_ERR_STAT_SUCCESS;
1078+ }
1079+ default:
1080+ panic("[FFA] Undefined response function (0x%lx)", res.a0);
1081+ }
1082+}
1083+
1084+/**
1085+ * ffa_release_rx_buffer - FFA_RX_RELEASE handler function
1086+ *
1087+ * This is the boot time function that invokes FFA_RX_RELEASE FF-A function
1088+ * to release the ownership of the RX buffer
1089+ *
1090+ * Return:
1091+ *
1092+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
1093+ */
1094+static int ffa_release_rx_buffer(void)
1095+{
1096+ FFA_DECLARE_ARGS;
1097+
1098+ ffa_dbg("[%s]", __func__);
1099+
1100+ if (!ffa_priv_data.invoke_ffa_fn)
1101+ panic("[FFA] no private data found\n");
1102+
1103+ a0 = FFA_RX_RELEASE;
1104+
1105+ ffa_priv_data.invoke_ffa_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
1106+
1107+ switch (res.a0) {
1108+ case FFA_ERROR:
1109+ {
1110+ if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
1111+ panic("[FFA] FFA_RX_RELEASE is not implemented at this FF-A instance\n");
1112+ else if (((int)res.a2) == FFA_ERR_STAT_DENIED)
1113+ panic("[FFA] Caller did not have ownership of the RX buffer\n");
1114+ else
1115+ panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
1116+ }
1117+ case FFA_SUCCESS:
1118+ ffa_info("RX buffer released");
1119+ return FFA_ERR_STAT_SUCCESS;
1120+
1121+ default:
1122+ panic("[FFA] Undefined response function (0x%lx)\n", res.a0);
1123+ }
1124+}
1125+
1126+/**
1127+ * ffa_uuid_are_identical - checks whether two given UUIDs are identical
1128+ * @uuid1: first UUID
1129+ * @uuid2: second UUID
1130+ *
1131+ * This is a boot time function used by ffa_read_partitions_info to search
1132+ * for a UUID in the partitions descriptors table
1133+ *
1134+ * Return:
1135+ *
1136+ * 1 when UUIDs match. Otherwise, 0
1137+ */
1138+int ffa_uuid_are_identical(const union ffa_partition_uuid *uuid1,
1139+ const union ffa_partition_uuid *uuid2)
1140+{
1141+ if (!uuid1 || !uuid2)
1142+ return 0;
1143+
1144+ return (!memcmp(uuid1, uuid2, sizeof(union ffa_partition_uuid)));
1145+}
1146+
1147+/**
1148+ * ffa_read_partitions_info - reads the data queried by FFA_PARTITION_INFO_GET
1149+ * and saves it in the private structure
1150+ * @count: The number of partitions queried
1151+ * @part_uuid: Pointer to the partition(s) UUID
1152+ *
1153+ * This is the boot time function that reads the partitions information
1154+ * returned by the FFA_PARTITION_INFO_GET and saves it in the private
1155+ * data structure.
1156+ *
1157+ * Return:
1158+ *
1159+ * The private data structure is updated with the partition(s) information
1160+ * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
1161+ */
1162+static int ffa_read_partitions_info(u32 count, union ffa_partition_uuid *part_uuid)
1163+{
1164+ ffa_dbg("[%s]", __func__);
1165+
1166+ if (!count) {
1167+ ffa_err("No partition detected");
1168+ return -ENODATA;
1169+ }
1170+
1171+ ffa_info("Reading partitions data from the RX buffer");
1172+
1173+#if CONFIG_IS_ENABLED(EFI_LOADER)
1174+
1175+ if (!part_uuid) {
1176+ /*
1177+ * querying information of all partitions
1178+ */
1179+ u64 data_pages;
1180+ u64 data_bytes;
1181+ efi_status_t efi_ret;
1182+ size_t buf_4k_pages = 0;
1183+ u32 desc_idx;
1184+ struct ffa_partition_info *parts_info;
1185+ int ret;
1186+
1187+ data_bytes = count * sizeof(struct ffa_partition_desc);
1188+ data_pages = efi_size_in_pages(data_bytes);
1189+
1190+ /*
1191+ * get the RX buffer size in pages
1192+ */
1193+ ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
1194+ if (ret != FFA_ERR_STAT_SUCCESS) {
1195+ ffa_err("Can not get the RX buffer size (error %d)", ret);
1196+ return ret;
1197+ }
1198+
1199+ if (data_pages > buf_4k_pages) {
1200+ ffa_err("Partitions data size exceeds the RX buffer size:");
1201+ ffa_err(" Sizes in pages: data %llu , RX buffer %lu ",
1202+ data_pages,
1203+ buf_4k_pages);
1204+
1205+ return -ENOMEM;
1206+ }
1207+
1208+ efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
1209+ EFI_RUNTIME_SERVICES_DATA,
1210+ data_pages,
1211+ (u64 *)&ffa_priv_data.partitions.descs);
1212+
1213+ if (efi_ret != EFI_SUCCESS) {
1214+ ffa_priv_data.partitions.descs = NULL;
1215+
1216+ ffa_err("Cannot allocate partitions data buffer (EFI error 0x%lx)",
1217+ efi_ret);
1218+
1219+ return -ENOBUFS;
1220+ }
1221+
1222+ /*
1223+ * convert the descs buffer physical address
1224+ * to virtual address
1225+ * This virtual address should not be unmapped
1226+ * descs is expected to be a virtual address
1227+ */
1228+ ffa_priv_data.partitions.descs =
1229+ (struct ffa_partition_desc *)
1230+ map_sysmem((phys_addr_t)
1231+ ffa_priv_data.partitions.descs, 0);
1232+
1233+ /*
1234+ * make sure the buffer is clean before use
1235+ */
1236+ memset(ffa_priv_data.partitions.descs, 0,
1237+ data_pages * SZ_4K);
1238+
1239+ ffa_info("Copying %lld page(s) of partitions data from RX buffer",
1240+ data_pages);
1241+
1242+ /*
1243+ * convert the RX buffer physical address to
1244+ * virtual address
1245+ */
1246+ parts_info = (struct ffa_partition_info *)
1247+ map_sysmem((phys_addr_t)
1248+ ffa_priv_data.pair.rxbuf, 0);
1249+
1250+ for (desc_idx = 0 ; desc_idx < count ; desc_idx++) {
1251+ ffa_priv_data.partitions.descs[desc_idx].info =
1252+ parts_info[desc_idx];
1253+
1254+ ffa_info("Partition ID %x : info cached",
1255+ ffa_priv_data.partitions.descs[desc_idx].info.id);
1256+ }
1257+ unmap_sysmem(parts_info);
1258+
1259+ ffa_priv_data.partitions.count = count;
1260+
1261+ ffa_info("%d partition(s) found and cached", count);
1262+
1263+ } else {
1264+ u32 rx_desc_idx, cached_desc_idx;
1265+ struct ffa_partition_info *parts_info;
1266+ u8 desc_found;
1267+
1268+ /*
1269+ * convert the RX buffer physical address to virtual address
1270+ */
1271+ parts_info = (struct ffa_partition_info *)
1272+ map_sysmem((phys_addr_t)ffa_priv_data.pair.rxbuf, 0);
1273+
1274+ /*
1275+ * search for the SP IDs read from the RX buffer
1276+ * in the already cached SPs.
1277+ * Update the UUID when ID found.
1278+ */
1279+ for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) {
1280+ desc_found = 0;
1281+
1282+ /*
1283+ * search the current ID in the cached partitions
1284+ */
1285+ for (cached_desc_idx = 0;
1286+ cached_desc_idx < ffa_priv_data.partitions.count;
1287+ cached_desc_idx++) {
1288+ /*
1289+ * save the UUID
1290+ */
1291+ if (ffa_priv_data.partitions.descs[cached_desc_idx].info.id ==
1292+ parts_info[rx_desc_idx].id) {
1293+ ffa_priv_data.partitions.descs[cached_desc_idx].UUID =
1294+ *part_uuid;
1295+
1296+ desc_found = 1;
1297+ break;
1298+ }
1299+ }
1300+
1301+ if (!desc_found) {
1302+ unmap_sysmem(parts_info);
1303+ return -ENODATA;
1304+ }
1305+ }
1306+ unmap_sysmem(parts_info);
1307+ }
1308+#else
1309+#warning "arm_ffa: reading FFA_PARTITION_INFO_GET data not implemented"
1310+#endif
1311+
1312+ return FFA_ERR_STAT_SUCCESS;
1313+}
1314+
1315+/**
1316+ * ffa_query_partitions_info - invokes FFA_PARTITION_INFO_GET
1317+ * and saves partitions data
1318+ * @part_uuid: Pointer to the partition(s) UUID
1319+ * @pcount: Pointer to the number of partitions variable filled when querying
1320+ *
1321+ * This is the boot time function that executes the FFA_PARTITION_INFO_GET
1322+ * to query the partitions data. Then, it calls ffa_read_partitions_info
1323+ * to save the data in the private data structure.
1324+ *
1325+ * After reading the data the RX buffer is released using ffa_release_rx_buffer
1326+ *
1327+ * Return:
1328+ *
1329+ * When part_uuid is NULL, all partitions data are retrieved from secure world
1330+ * When part_uuid is non NULL, data for partitions matching the given UUID are
1331+ * retrieved and the number of partitions is returned
1332+ * FFA_ERR_STAT_SUCCESS is returned on success. Otherwise, failure
1333+ */
1334+static int ffa_query_partitions_info(union ffa_partition_uuid *part_uuid,
1335+ u32 *pcount)
1336+{
1337+ unsigned long a0 = 0;
1338+ union ffa_partition_uuid query_uuid = {0};
1339+ unsigned long a5 = 0;
1340+ unsigned long a6 = 0;
1341+ unsigned long a7 = 0;
1342+ struct arm_smccc_res res = {0};
1343+
1344+ ffa_dbg("[%s]", __func__);
1345+
1346+ if (!ffa_priv_data.invoke_ffa_fn)
1347+ panic("[FFA] no private data found\n");
1348+
1349+ a0 = FFA_PARTITION_INFO_GET;
1350+
1351+ /*
1352+ * If a UUID is specified. Information for one or more
1353+ * partitions in the system is queried. Otherwise, information
1354+ * for all installed partitions is queried
1355+ */
1356+
1357+ if (part_uuid) {
1358+ if (!pcount)
1359+ return -EINVAL;
1360+
1361+ query_uuid = *part_uuid;
1362+ }
1363+
1364+ ffa_priv_data.invoke_ffa_fn(a0, query_uuid.words.a1, query_uuid.words.a2,
1365+ query_uuid.words.a3, query_uuid.words.a4,
1366+ a5, a6, a7, &res);
1367+
1368+ switch (res.a0) {
1369+ case FFA_ERROR:
1370+ {
1371+ switch (((int)res.a2)) {
1372+ case FFA_ERR_STAT_INVALID_PARAMETERS:
1373+ ffa_err("Unrecognized UUID");
1374+ return -EPERM;
1375+ case FFA_ERR_STAT_NO_MEMORY:
1376+ ffa_err("Results cannot fit in RX buffer of the caller");
1377+ return -ENOMEM;
1378+ case FFA_ERR_STAT_DENIED:
1379+ ffa_err("Callee is not in a state to handle this request");
1380+ return -EACCES;
1381+ case FFA_ERR_STAT_NOT_SUPPORTED:
1382+ ffa_err("This function is not implemented at this FF-A instance");
1383+ return -EOPNOTSUPP;
1384+ case FFA_ERR_STAT_BUSY:
1385+ ffa_err("RX buffer of the caller is not free");
1386+ return -EBUSY;
1387+ default:
1388+ ffa_err("Undefined error (%d)", ((int)res.a2));
1389+ return -EINVAL;
1390+ }
1391+ }
1392+ case FFA_SUCCESS:
1393+ {
1394+ int ret;
1395+
1396+ /*
1397+ * res.a2 contains the count of partition information descriptors
1398+ * populated in the RX buffer
1399+ */
1400+ if (res.a2) {
1401+ ret = ffa_read_partitions_info(res.a2, part_uuid);
1402+ if (ret)
1403+ ffa_err("Failed to read partition(s) data , error (%d)", ret);
1404+ }
1405+
1406+ /*
1407+ * return the SP count
1408+ */
1409+ if (part_uuid) {
1410+ if (!ret)
1411+ *pcount = res.a2;
1412+ else
1413+ *pcount = 0;
1414+ }
1415+ /*
1416+ * After calling FFA_PARTITION_INFO_GET the buffer ownership
1417+ * is assigned to the consumer (u-boot). So, we need to give
1418+ * the ownership back to the secure world
1419+ */
1420+ ret = ffa_release_rx_buffer();
1421+
1422+ if (!part_uuid && !res.a2) {
1423+ ffa_err("[FFA] no partition installed in the system");
1424+ return -ENODEV;
1425+ }
1426+
1427+ return ret;
1428+ }
1429+ default:
1430+ ffa_err("Undefined response function (0x%lx)", res.a0);
1431+ return -EINVAL;
1432+ }
1433+}
1434+
1435+/**
1436+ * ffa_get_partitions_info - FFA_PARTITION_INFO_GET handler function
1437+ * @func_data: Pointer to the FF-A function arguments container structure.
1438+ * The passed arguments:
1439+ * Mode 1: When getting from the driver the number of
1440+ * secure partitions:
1441+ * @data0_size: UUID size
1442+ * @data0: pointer to the UUID (little endian)
1443+ * @data1_size: size of the number of partitions
1444+ * variable
1445+ * @data1: pointer to the number of partitions
1446+ * variable. The variable will be set
1447+ * by the driver
1448+ * Mode 2: When requesting the driver to return the
1449+ * partitions information:
1450+ * @data0_size: UUID size
1451+ * @data0: pointer to the UUID (little endian)
1452+ * @data1_size: size of the SPs information buffer
1453+ * @data1: pointer to SPs information buffer
1454+ * (allocated by the client).
1455+ * The buffer will be filled by the driver
1456+ *
1457+ * This is the boot time function that queries the secure partition data from
1458+ * the private data structure. If not found, it invokes FFA_PARTITION_INFO_GET
1459+ * FF-A function to query the partition information from secure world.
1460+ *
1461+ * A client of the FF-A driver should know the UUID of the service it wants to
1462+ * access. It should use the UUID to request the FF-A driver to provide the
1463+ * partition(s) information of the service. The FF-A driver uses
1464+ * PARTITION_INFO_GET to obtain this information. This is implemented through
1465+ * ffa_get_partitions_info function.
1466+ * A new FFA_PARTITION_INFO_GET call is issued (first one performed through
1467+ * ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
1468+ * They are not saved (already done). We only update the UUID in the cached area.
1469+ * This assumes that partitions data does not change in the secure world.
1470+ * Otherwise u-boot will have an outdated partition data. The benefit of caching
1471+ * the information in the FF-A driver is to accommodate discovery after
1472+ * ExitBootServices().
1473+ *
1474+ * When invoked through a client request, ffa_get_partitions_info should be
1475+ * called twice. First call is to get from the driver the number of secure
1476+ * partitions (SPs) associated to a particular UUID.
1477+ * Then, the caller (client) allocates the buffer to host the SPs data and
1478+ * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated
1479+ * buffer.
1480+ *
1481+ * To achieve the mechanism described above, ffa_get_partitions_info uses the
1482+ * following functions:
1483+ * ffa_read_partitions_info
1484+ * ffa_query_partitions_info
1485+ *
1486+ * Return:
1487+ *
1488+ * @data1: When pointing to the number of partitions variable, the number is
1489+ * set by the driver.
1490+ * When pointing to the partitions information buffer, the buffer will be
1491+ * filled by the driver.
1492+ *
1493+ * On success FFA_ERR_STAT_SUCCESS is returned. Otherwise, failure
1494+ */
1495+static int ffa_get_partitions_info(struct ffa_interface_data *func_data)
1496+{
1497+ /*
1498+ * fill_data:
1499+ * 0: return the SP count
1500+ * 1: fill SP data and return it to the caller
1501+ * -1: undefined mode
1502+ */
1503+ int fill_data = -1;
1504+ u32 desc_idx, client_desc_idx;
1505+ union ffa_partition_uuid *part_uuid;
1506+ u32 client_desc_max_cnt;
1507+ u32 parts_found = 0;
1508+
1509+ ffa_dbg("[%s]", __func__);
1510+
1511+ if (!func_data) {
1512+ ffa_err("No function data provided");
1513+ return -EINVAL;
1514+ }
1515+
1516+ if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs)
1517+ panic("[FFA] No partition installed\n");
1518+
1519+ if (func_data->data0_size == sizeof(union ffa_partition_uuid) &&
1520+ func_data->data0 &&
1521+ func_data->data1_size == sizeof(u32) &&
1522+ func_data->data1) {
1523+ /*
1524+ * data0 (in): pointer to UUID
1525+ * data1 (in): pointer to SP count
1526+ * Out: SP count returned in the count variable pointed by data1
1527+ */
1528+
1529+ fill_data = 0;
1530+
1531+ ffa_info("Preparing for checking partitions count");
1532+
1533+ } else if ((func_data->data0_size == sizeof(union ffa_partition_uuid)) &&
1534+ func_data->data0 &&
1535+ (func_data->data1_size >= sizeof(struct ffa_partition_info)) &&
1536+ !(func_data->data1_size % sizeof(struct ffa_partition_info)) &&
1537+ func_data->data1) {
1538+ /*
1539+ * data0 (in): pointer to UUID
1540+ * data1 (in): pointer to SPs descriptors buffer
1541+ * (created by the client)
1542+ * Out: SPs descriptors returned in the buffer
1543+ * pointed by data1
1544+ */
1545+
1546+ fill_data = 1;
1547+
1548+ client_desc_idx = 0;
1549+
1550+ /*
1551+ * number of empty descriptors preallocated by the caller
1552+ */
1553+ client_desc_max_cnt =
1554+ func_data->data1_size / sizeof(struct ffa_partition_info);
1555+
1556+ ffa_info("Preparing for filling partitions info");
1557+
1558+ } else {
1559+ ffa_err("Invalid function arguments provided");
1560+ return -EINVAL;
1561+ }
1562+
1563+ part_uuid = (union ffa_partition_uuid *)func_data->data0;
1564+
1565+ ffa_info("Searching partitions using the provided UUID");
1566+
1567+#ifdef DEBUG
1568+ {
1569+ u32 dbg_uuid_cnt;
1570+
1571+ ffa_dbg("UUID: [LSB]");
1572+
1573+ for (dbg_uuid_cnt = 0 ; dbg_uuid_cnt < UUID_SIZE ; dbg_uuid_cnt++)
1574+ ffa_dbg(" %02x", part_uuid->bytes[dbg_uuid_cnt]);
1575+ }
1576+#endif
1577+
1578+ /*
1579+ * search in the cached partitions
1580+ */
1581+ for (desc_idx = 0;
1582+ desc_idx < ffa_priv_data.partitions.count;
1583+ desc_idx++) {
1584+ if (ffa_uuid_are_identical(&ffa_priv_data.partitions.descs[desc_idx].UUID,
1585+ part_uuid)) {
1586+ ffa_info("Partition ID %x matches the provided UUID",
1587+ ffa_priv_data.partitions.descs[desc_idx].info.id);
1588+
1589+ parts_found++;
1590+
1591+ if (fill_data) {
1592+ /*
1593+ * trying to fill the partition info in data1
1594+ */
1595+
1596+ if (client_desc_idx < client_desc_max_cnt) {
1597+ ((struct ffa_partition_info *)
1598+ func_data->data1)[client_desc_idx++] =
1599+ ffa_priv_data.partitions.descs[desc_idx].info;
1600+ continue;
1601+ }
1602+
1603+ ffa_err("Failed to fill the current descriptor client buffer full");
1604+ return -ENOBUFS;
1605+ }
1606+ }
1607+ }
1608+
1609+ if (!parts_found) {
1610+ int ret;
1611+
1612+ ffa_info("No partition found. Querying framework ...");
1613+
1614+ ret = ffa_query_partitions_info(part_uuid, &parts_found);
1615+
1616+ if (ret == FFA_ERR_STAT_SUCCESS) {
1617+ if (!fill_data) {
1618+ *((u32 *)func_data->data1) = parts_found;
1619+
1620+ ffa_info("Number of partition(s) found matching the UUID: %d",
1621+ parts_found);
1622+ } else {
1623+ /*
1624+ * we want to read SPs info
1625+ */
1626+
1627+ /*
1628+ * If SPs data filled, retry searching SP info again
1629+ */
1630+ if (parts_found)
1631+ ret = ffa_get_partitions_info(func_data);
1632+ else
1633+ ret = -ENODATA;
1634+ }
1635+ }
1636+
1637+ return ret;
1638+ }
1639+
1640+ /* partition(s) found */
1641+ if (!fill_data)
1642+ *((u32 *)func_data->data1) = parts_found;
1643+
1644+ return FFA_ERR_STAT_SUCCESS;
1645+}
1646+
1647+/**
1648+ * ffa_cache_partitions_info - Queries and saves all secure partitions data
1649+ *
1650+ * This is a boot time function that invokes FFA_PARTITION_INFO_GET FF-A
1651+ * function to query from secure world all partitions information.
1652+ *
1653+ * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument.
1654+ * All installed partitions information are returned. We cache them in the
1655+ * resident private data structure and we keep the UUID field empty
1656+ * (in FF-A 1.0 UUID is not provided by the partition descriptor)
1657+ *
1658+ * This function is called at the device probing level.
1659+ * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data
1660+ *
1661+ * Return:
1662+ *
1663+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
1664+ */
1665+static int ffa_cache_partitions_info(void)
1666+{
1667+ ffa_dbg("[%s]", __func__);
1668+ return ffa_query_partitions_info(NULL, NULL);
1669+}
1670+
1671+/**
1672+ * ffa_msg_send_direct_req - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
1673+ * @func_data: Pointer to the FF-A function arguments container structure.
1674+ * The passed arguments:
1675+ * @data0_size: partition ID size
1676+ * @data0: pointer to the partition ID
1677+ * @data1_size: exchanged data size
1678+ * @data1: pointer to the data buffer preallocated by
1679+ * the client (in/out)
1680+ *
1681+ * This is the runtime function that implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
1682+ * FF-A functions.
1683+ *
1684+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
1685+ * The response from the secure partition is handled by reading the
1686+ * FFA_MSG_SEND_DIRECT_RESP arguments.
1687+ *
1688+ * The maximum size of the data that can be exchanged is 20 bytes which is
1689+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
1690+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
1691+ *
1692+ * Return:
1693+ *
1694+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
1695+ */
1696+static int __ffa_runtime ffa_msg_send_direct_req(struct ffa_interface_data
1697+ *func_data)
1698+{
1699+ u16 dst_part_id;
1700+ unsigned long a0 = 0;
1701+ unsigned long a1 = 0;
1702+ unsigned long a2 = 0;
1703+ struct ffa_send_direct_data *msg;
1704+ struct arm_smccc_res res = {0};
1705+
1706+ ffa_dbg("[%s]", __func__);
1707+
1708+ if (!ffa_priv_data.invoke_ffa_fn)
1709+ panic("[FFA] no private data found\n");
1710+
1711+ if (!func_data)
1712+ return -EINVAL;
1713+
1714+ if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs)
1715+ panic("[FFA] no partition installed\n");
1716+
1717+ if (func_data->data0_size != sizeof(u16) ||
1718+ !func_data->data0 ||
1719+ func_data->data1_size != FFA_MSG_SEND_DIRECT_MAX_SIZE ||
1720+ !func_data->data1) {
1721+ ffa_err("Undefined interface parameters");
1722+ return -EINVAL;
1723+ }
1724+
1725+ dst_part_id = *((u16 *)func_data->data0);
1726+ msg = func_data->data1;
1727+
1728+ ffa_dbg("Sending data to partition ID 0x%x", dst_part_id);
1729+
1730+ a0 = FFA_MSG_SEND_DIRECT_REQ;
1731+
1732+ a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id) |
1733+ PREP_PART_ENDPOINT_ID(dst_part_id);
1734+
1735+ ffa_priv_data.invoke_ffa_fn(a0, a1, a2,
1736+ msg->a3,
1737+ msg->a4,
1738+ msg->a5,
1739+ msg->a6,
1740+ msg->a7,
1741+ &res);
1742+
1743+ while (res.a0 == FFA_INTERRUPT)
1744+ ffa_priv_data.invoke_ffa_fn(FFA_RUN, res.a1,
1745+ 0, 0, 0, 0, 0, 0,
1746+ &res);
1747+
1748+ switch (res.a0) {
1749+ case FFA_ERROR:
1750+ {
1751+ switch (((int)res.a2)) {
1752+ case FFA_ERR_STAT_INVALID_PARAMETERS:
1753+ ffa_err("Invalid endpoint ID or non-zero reserved register");
1754+ return -EPERM;
1755+ case FFA_ERR_STAT_ABORTED:
1756+ panic("[FFA] Message target ran into unexpected error and has aborted\n");
1757+ case FFA_ERR_STAT_DENIED:
1758+ panic("[FFA] Callee is not in a state to handle this request\n");
1759+ case FFA_ERR_STAT_NOT_SUPPORTED:
1760+ panic("[FFA] This function is not implemented at this FF-A instance\n");
1761+ case FFA_ERR_STAT_BUSY:
1762+ panic("[FFA] Message target is busy\n");
1763+ default:
1764+ panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
1765+ }
1766+ }
1767+ case FFA_SUCCESS:
1768+
1769+ ffa_dbg("Message sent with no response");
1770+ return FFA_ERR_STAT_SUCCESS;
1771+
1772+ case FFA_MSG_SEND_DIRECT_RESP:
1773+
1774+ ffa_dbg("Message sent with response");
1775+
1776+ /*
1777+ * extract the 32-bit wide return data
1778+ */
1779+ msg->a3 = (u32)res.a3;
1780+ msg->a4 = (u32)res.a4;
1781+ msg->a5 = (u32)res.a5;
1782+ msg->a6 = (u32)res.a6;
1783+ msg->a7 = (u32)res.a7;
1784+
1785+ return FFA_ERR_STAT_SUCCESS;
1786+
1787+ default:
1788+ panic("[FFA] Undefined response function (0x%lx)\n", res.a0);
1789+ }
1790+}
1791+
1792+/**
1793+ * invoke_ffa_drv_api - The driver dispatcher function
1794+ * @func_id: The FF-A function to be used
1795+ * @func_data: Pointer to the FF-A function arguments container
1796+ * structure. This also includes pointers to the
1797+ * returned data needed by clients.
1798+ * The dispatcher is a runtime function that selects the FF-A function handler
1799+ * based on the input FF-A function ID.
1800+ * The input arguments are passed to the handler function.
1801+ *
1802+ * Return:
1803+ *
1804+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
1805+ */
1806+int __ffa_runtime invoke_ffa_drv_api(u32 func_id,
1807+ struct ffa_interface_data *func_data)
1808+{
1809+ if (!ffa_priv_data.dev)
1810+ panic("[FFA] no device found\n");
1811+
1812+ switch (func_id) {
1813+ case FFA_PARTITION_INFO_GET:
1814+ return ffa_get_partitions_info(func_data);
1815+ case FFA_RXTX_UNMAP:
1816+ return ffa_unmap_rxtx_buffers();
1817+ case FFA_MSG_SEND_DIRECT_REQ:
1818+ return ffa_msg_send_direct_req(func_data);
1819+ default:
1820+
1821+ ffa_err("Undefined FF-A interface (%d)", func_id);
1822+
1823+ return -EINVAL;
1824+ }
1825+}
1826+
1827+/**
1828+ * ffa_init_private_data - Initialization of the private data
1829+ * @dev: the arm_ffa device
1830+ *
1831+ * This boot time function reads data from the platform data structure
1832+ * and populates the private data structure
1833+ *
1834+ * Return:
1835+ *
1836+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
1837+ */
1838+static int ffa_init_private_data(struct udevice *dev)
1839+{
1840+ struct ffa_pdata *pdata = dev_get_plat(dev);
1841+
1842+ ffa_priv_data.conduit = pdata->conduit;
1843+
1844+ if (ffa_priv_data.conduit == FFA_CONDUIT_SMC) {
1845+ ffa_priv_data.invoke_ffa_fn = arm_ffa_smccc_smc;
1846+ } else {
1847+ ffa_err("Undefined FF-A conduit (%d)", ffa_priv_data.conduit);
1848+ return -EINVAL;
1849+ }
1850+
1851+ ffa_info("Conduit is %s",
1852+ ((ffa_priv_data.conduit == FFA_CONDUIT_SMC) ?
1853+ "SMC" : "NOT SUPPORTED"));
1854+
1855+ return FFA_ERR_STAT_SUCCESS;
1856+}
1857+
1858+/**
1859+ * ffa_probe - The driver probe function
1860+ * @dev: the arm_ffa device
1861+ *
1862+ * Probing is done at boot time and triggered by the uclass device discovery.
1863+ * At probe level the following actions are done:
1864+ * - initialization of the driver private data structure
1865+ * - querying from secure world the FF-A framework version
1866+ * - querying from secure world the u-boot endpoint ID
1867+ * - querying from secure world the supported features of the specified FF-A calls
1868+ * - mapping the RX/TX buffers
1869+ * - querying from secure world all the partitions information
1870+ *
1871+ * All data queried from secure world is saved in the resident private data structure.
1872+ *
1873+ * The probe will fail if either FF-A framework is not detected or the
1874+ * FF-A requests are not behaving correctly. This ensures that the
1875+ * driver is not installed and its operations are not exported to the clients.
1876+ * However, once the driver is successfully probed and an FF-A anomaly is
1877+ * detected when clients invoke the driver operations, the driver cause
1878+ * u-boot to panic because the client would not know what to do in such conditions.
1879+ *
1880+ * Return:
1881+ *
1882+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
1883+ */
1884+static int ffa_probe(struct udevice *dev)
1885+{
1886+ int ret;
1887+ size_t buf_4k_pages = 0;
1888+
1889+ ffa_dbg("[%s]: initializing the FF-A driver", __func__);
1890+
1891+ ret = ffa_init_private_data(dev);
1892+
1893+ if (ret != FFA_ERR_STAT_SUCCESS)
1894+ return ret;
1895+
1896+ ret = ffa_get_version();
1897+
1898+ if (ret != FFA_ERR_STAT_SUCCESS)
1899+ return ret;
1900+
1901+ ret = ffa_get_endpoint_id();
1902+
1903+ if (ret != FFA_ERR_STAT_SUCCESS)
1904+ return ret;
1905+
1906+ ret = ffa_get_rxtx_map_features();
1907+
1908+ if (ret != FFA_ERR_STAT_SUCCESS)
1909+ return ret;
1910+
1911+ ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
1912+
1913+ if (ret != FFA_ERR_STAT_SUCCESS)
1914+ return ret;
1915+
1916+ ret = ffa_map_rxtx_buffers(buf_4k_pages);
1917+
1918+ if (ret != FFA_ERR_STAT_SUCCESS)
1919+ return ret;
1920+
1921+ ret = ffa_cache_partitions_info();
1922+
1923+ if (ret != FFA_ERR_STAT_SUCCESS) {
1924+ ffa_free_rxtx_buffers(buf_4k_pages);
1925+ return ret;
1926+ }
1927+
1928+ ffa_dbg("[%s]: initialization done", __func__);
1929+
1930+ return FFA_ERR_STAT_SUCCESS;
1931+}
1932+
1933+/**
1934+ * ffa_of_to_plat - Reads the device tree node
1935+ * @dev: the arm_ffa device
1936+ *
1937+ * This boot time function reads data from the device tree node and populates
1938+ * the platform data structure
1939+ *
1940+ * Return:
1941+ *
1942+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
1943+ */
1944+static int ffa_of_to_plat(struct udevice *dev)
1945+{
1946+ struct ffa_pdata *pdata = dev_get_plat(dev);
1947+ const char *conduit;
1948+
1949+ ffa_dbg("[%s]", __func__);
1950+
1951+ conduit = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "method", NULL);
1952+
1953+ if (strcmp("smc", conduit)) {
1954+ ffa_err("Unsupported conduit");
1955+ return -EINVAL;
1956+ }
1957+
1958+ pdata->conduit = FFA_CONDUIT_SMC;
1959+
1960+ return FFA_ERR_STAT_SUCCESS;
1961+}
1962+
1963+/**
1964+ * ffa_drv_ops - The driver operations runtime structure
1965+ * @invoke_func: The driver dispatcher
1966+ */
1967+struct ffa_ops __ffa_runtime_data ffa_drv_ops = {
1968+ .invoke_func = invoke_ffa_drv_api
1969+};
1970+
1971+/**
1972+ * ffa_device_get_ops - driver operations getter
1973+ *
1974+ * Return:
1975+ * This runtime function returns a pointer to the driver operations structure
1976+ */
1977+const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void)
1978+{
1979+ return &ffa_drv_ops;
1980+}
1981+
1982+/**
1983+ * Defining the device tree compatible string
1984+ */
1985+
1986+static const struct udevice_id ffa_match_id[] = {
1987+ {"arm,ffa", 0},
1988+ {},
1989+};
1990+
1991+/**
1992+ * Declaring the arm_ffa driver under UCLASS_FFA
1993+ */
1994+
1995+U_BOOT_DRIVER(arm_ffa) = {
1996+ .name = "arm_ffa",
1997+ .of_match = ffa_match_id,
1998+ .id = UCLASS_FFA,
1999+ .of_to_plat = ffa_of_to_plat,
2000+ .probe = ffa_probe,
2001+ .plat_auto = sizeof(struct ffa_pdata),
2002+};
2003diff --git a/include/arm_ffa.h b/include/arm_ffa.h
2004new file mode 100644
2005index 000000000000..313f46f74764
2006--- /dev/null
2007+++ b/include/arm_ffa.h
2008@@ -0,0 +1,191 @@
2009+/* SPDX-License-Identifier: GPL-2.0+ */
2010+/*
2011+ * (C) Copyright 2021 ARM Limited
2012+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
2013+ */
2014+
2015+#ifndef __ARM_FFA_H
2016+#define __ARM_FFA_H
2017+
2018+#include <linux/arm-smccc.h>
2019+#include <linux/printk.h>
2020+
2021+/*
2022+ * This header is public. It can be used by clients to access
2023+ * data structures and definitions they need
2024+ */
2025+
2026+/*
2027+ * Macros for displaying logs
2028+ */
2029+
2030+#define ffa_dbg(fmt, ...) pr_debug("[FFA] " fmt "\n", ##__VA_ARGS__)
2031+#define ffa_info(fmt, ...) pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
2032+#define ffa_err(fmt, ...) pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
2033+
2034+/*
2035+ * The driver operations success error code
2036+ */
2037+#define FFA_ERR_STAT_SUCCESS (0)
2038+
2039+#if CONFIG_IS_ENABLED(EFI_LOADER)
2040+
2041+#include <efi_loader.h>
2042+
2043+/*
2044+ * __ffa_runtime_data and __ffa_runtime - controls whether data/code are
2045+ * available after calling the EFI ExitBootServices service.
2046+ * Data/code tagged with these keywords are resident (available at boot time and
2047+ * at runtime)
2048+ */
2049+
2050+#define __ffa_runtime_data __efi_runtime_data
2051+#define __ffa_runtime __efi_runtime
2052+
2053+#else
2054+
2055+#define __ffa_runtime_data
2056+#define __ffa_runtime
2057+
2058+#endif
2059+
2060+/*
2061+ * Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver
2062+ */
2063+
2064+#define FFA_SMC(calling_convention, func_num) \
2065+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention), \
2066+ ARM_SMCCC_OWNER_STANDARD, (func_num))
2067+
2068+#define FFA_SMC_32(func_num) FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
2069+
2070+#define FFA_VERSION FFA_SMC_32(0x63)
2071+#define FFA_ID_GET FFA_SMC_32(0x69)
2072+#define FFA_FEATURES FFA_SMC_32(0x64)
2073+#define FFA_PARTITION_INFO_GET FFA_SMC_32(0x68)
2074+#define FFA_RXTX_MAP FFA_SMC_32(0x66)
2075+#define FFA_RXTX_UNMAP FFA_SMC_32(0x67)
2076+#define FFA_RX_RELEASE FFA_SMC_32(0x65)
2077+#define FFA_MSG_SEND_DIRECT_REQ FFA_SMC_32(0x6F)
2078+#define FFA_MSG_SEND_DIRECT_RESP FFA_SMC_32(0x70)
2079+#define FFA_RUN FFA_SMC_32(0x6D)
2080+#define FFA_ERROR FFA_SMC_32(0x60)
2081+#define FFA_SUCCESS FFA_SMC_32(0x61)
2082+#define FFA_INTERRUPT FFA_SMC_32(0x62)
2083+
2084+/*
2085+ * struct ffa_partition_info - Partition information descriptor
2086+ * @id: Partition ID
2087+ * @exec_ctxt: Execution context count
2088+ * @properties: Partition properties
2089+ *
2090+ * Data structure containing information about partitions instantiated in the system
2091+ * This structure is filled with the data queried by FFA_PARTITION_INFO_GET
2092+ */
2093+struct __packed ffa_partition_info {
2094+ u16 id;
2095+ u16 exec_ctxt;
2096+/* partition supports receipt of direct requests */
2097+#define FFA_PARTITION_DIRECT_RECV BIT(0)
2098+/* partition can send direct requests. */
2099+#define FFA_PARTITION_DIRECT_SEND BIT(1)
2100+/* partition can send and receive indirect messages. */
2101+#define FFA_PARTITION_INDIRECT_MSG BIT(2)
2102+ u32 properties;
2103+};
2104+
2105+/*
2106+ * struct ffa_send_direct_data - Data structure hosting the data
2107+ * used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
2108+ * @a3-a7: Data read/written from/to w3-w7 registers
2109+ *
2110+ * Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
2111+ * or read from FFA_MSG_SEND_DIRECT_RESP
2112+ */
2113+struct __packed ffa_send_direct_data {
2114+ u32 a3; /* w3 */
2115+ u32 a4; /* w4 */
2116+ u32 a5; /* w5 */
2117+ u32 a6; /* w6 */
2118+ u32 a7; /* w7 */
2119+};
2120+
2121+#define FFA_MSG_SEND_DIRECT_MAX_SIZE (sizeof(struct ffa_send_direct_data))
2122+
2123+/* UUID data size */
2124+#define UUID_SIZE (16)
2125+
2126+/*
2127+ * union ffa_partition_uuid - Data union hosting the UUID
2128+ * transmitted by FFA_PARTITION_INFO_GET
2129+ * @words: data structure giving 32-bit words access to the UUID data
2130+ * @bytes: data structure giving byte access to the UUID data
2131+ *
2132+ * The structure holds little-endian UUID data.
2133+ */
2134+union ffa_partition_uuid {
2135+ struct __packed words {
2136+ u32 a1; /* w1 */
2137+ u32 a2; /* w2 */
2138+ u32 a3; /* w3 */
2139+ u32 a4; /* w4 */
2140+ } words;
2141+ u8 bytes[UUID_SIZE];
2142+};
2143+
2144+/**
2145+ * struct ffa_interface_data - generic FF-A interface data structure used to exchange
2146+ * data between user layers and the driver
2147+ * @data0_size: size of the first argument
2148+ * @data0: pointer to the first argument
2149+ * @data1_size>: size of the second argument
2150+ * @data1: pointer to the second argument
2151+ *
2152+ * Using this structure user layers can pass various types of data with different sizes.
2153+ * The driver internal functions can detect the nature of this data, verfy compliance
2154+ * then execute the request when appropriate.
2155+ */
2156+struct ffa_interface_data {
2157+ u32 data0_size; /* size of the first argument */
2158+ void *data0; /* pointer to the first argument */
2159+ u32 data1_size; /* size of the second argument */
2160+ void *data1; /* pointer to the second argument */
2161+};
2162+
2163+/**
2164+ * struct ffa_ops - The driver operations structure
2165+ * @invoke_func: function pointer to the invoke function
2166+ *
2167+ * The data structure providing all the operations supported by the driver.
2168+ * This structure is resident.
2169+ */
2170+struct ffa_ops {
2171+ /* the driver dispatcher */
2172+ int (*invoke_func)(u32 func_id, struct ffa_interface_data *func_data);
2173+};
2174+
2175+/**
2176+ * The device driver and the Uclass driver public functions
2177+ */
2178+
2179+/**
2180+ * ffa_get_invoke_func - performs a call to the FF-A driver dispatcher
2181+ */
2182+int __ffa_runtime ffa_get_invoke_func(u32 func_id,
2183+ struct ffa_interface_data *func_data);
2184+
2185+/**
2186+ * ffa_device_get_ops - driver operations getter
2187+ */
2188+const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void);
2189+
2190+/**
2191+ * ffa_get_device - probes the arm_ffa device
2192+ */
2193+int ffa_get_device(void);
2194+
2195+/**
2196+ * ffa_init_device - probes the arm_ffa device
2197+ */
2198+int ffa_init_device(void);
2199+#endif
2200diff --git a/include/arm_ffa_helper.h b/include/arm_ffa_helper.h
2201new file mode 100644
2202index 000000000000..0e143e54511e
2203--- /dev/null
2204+++ b/include/arm_ffa_helper.h
2205@@ -0,0 +1,45 @@
2206+/* SPDX-License-Identifier: GPL-2.0+ */
2207+/*
2208+ * (C) Copyright 2021 ARM Limited
2209+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
2210+ */
2211+
2212+#ifndef __ARM_FFA_HELPER_H
2213+#define __ARM_FFA_HELPER_H
2214+
2215+#include <arm_ffa.h>
2216+
2217+/*
2218+ * This header is public. Including this header provides all data structures
2219+ * and definitions needed by clients to use the FF-A transport driver
2220+ *
2221+ * It also provides helper functions allowing to pass data and invoke FF-A functions
2222+ */
2223+
2224+/**
2225+ * ffa_helper_get_partitions_info - Wrapper function for FFA_PARTITION_INFO_GET
2226+ */
2227+int ffa_helper_get_partitions_info(struct ffa_interface_data *func_data);
2228+
2229+/**
2230+ * ffa_helper_unmap_rxtx_buffers - Wrapper function for FFA_RXTX_UNMAP
2231+ */
2232+int ffa_helper_unmap_rxtx_buffers(void);
2233+
2234+/**
2235+ * ffa_helper_msg_send_direct_req - Wrapper function for
2236+ * FFA_MSG_SEND_DIRECT_{REQ,RESP}
2237+ */
2238+int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data
2239+ *func_data);
2240+
2241+/**
2242+ * ffa_helper_init_device - Wrapper function for probing the arm_ffa device
2243+ */
2244+int ffa_helper_init_device(void);
2245+
2246+/**
2247+ * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
2248+ */
2249+int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin);
2250+#endif
2251diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
Patrick Williams92b42cb2022-09-03 06:53:57 -05002252index 3ba69ad9a084..732441824557 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002253--- a/include/dm/uclass-id.h
2254+++ b/include/dm/uclass-id.h
Patrick Williams92b42cb2022-09-03 06:53:57 -05002255@@ -55,6 +55,7 @@ enum uclass_id {
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002256 UCLASS_EFI_MEDIA, /* Devices provided by UEFI firmware */
2257 UCLASS_ETH, /* Ethernet device */
2258 UCLASS_ETH_PHY, /* Ethernet PHY device */
2259+ UCLASS_FFA, /* Arm Firmware Framework for Armv8-A */
2260 UCLASS_FIRMWARE, /* Firmware */
2261 UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */
2262 UCLASS_GPIO, /* Bank of general-purpose I/O pins */
2263diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
2264index 7f2be2339475..54980a130fdb 100644
2265--- a/include/linux/arm-smccc.h
2266+++ b/include/linux/arm-smccc.h
2267@@ -1,6 +1,8 @@
2268 /* SPDX-License-Identifier: GPL-2.0 */
2269 /*
2270 * Copyright (c) 2015, Linaro Limited
2271+ * (C) Copyright 2021 ARM Limited
2272+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
2273 */
2274 #ifndef __LINUX_ARM_SMCCC_H
2275 #define __LINUX_ARM_SMCCC_H
2276@@ -57,13 +59,17 @@
2277 #include <linux/types.h>
2278 /**
2279 * struct arm_smccc_res - Result from SMC/HVC call
2280- * @a0-a3 result values from registers 0 to 3
2281+ * @a0-a7 result values from registers 0 to 7
2282 */
2283 struct arm_smccc_res {
2284 unsigned long a0;
2285 unsigned long a1;
2286 unsigned long a2;
2287 unsigned long a3;
2288+ unsigned long a4;
2289+ unsigned long a5;
2290+ unsigned long a6;
2291+ unsigned long a7;
2292 };
2293
2294 /**
2295@@ -113,6 +119,26 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
2296 unsigned long a5, unsigned long a6, unsigned long a7,
2297 struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
2298
2299+#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT))
2300+/**
2301+ * __arm_ffa_smccc_smc() - make SMC calls used for FF-A transport
2302+ * @a0-a7: arguments passed in 64-bit registers x0 to x7
2303+ * @res: result values from 64-bit registers x0 to x7
2304+ *
2305+ * This function is used to make SMC calls following SMC32 Calling Convention.
2306+ * The content of the supplied parameters is copied to registers x0 to x7 prior
2307+ * to the SMC instruction. The SMC call return data is 32-bit data read from
2308+ * registers x0 tp x7.
2309+ */
2310+asmlinkage void __arm_ffa_smccc_smc(unsigned long a0, unsigned long a1,
2311+ unsigned long a2, unsigned long a3, unsigned long a4,
2312+ unsigned long a5, unsigned long a6, unsigned long a7,
2313+ struct arm_smccc_res *res);
2314+
2315+#define arm_ffa_smccc_smc __arm_ffa_smccc_smc
2316+
2317+#endif
2318+
2319 #define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
2320
2321 #define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
2322diff --git a/lib/Kconfig b/lib/Kconfig
Patrick Williams92b42cb2022-09-03 06:53:57 -05002323index acc0ac081a44..65db65c3c4cd 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002324--- a/lib/Kconfig
2325+++ b/lib/Kconfig
Patrick Williams92b42cb2022-09-03 06:53:57 -05002326@@ -902,6 +902,7 @@ config SMBIOS_PARSER
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002327 source lib/efi/Kconfig
2328 source lib/efi_loader/Kconfig
2329 source lib/optee/Kconfig
2330+source lib/arm-ffa/Kconfig
2331
2332 config TEST_FDTDEC
2333 bool "enable fdtdec test"
2334diff --git a/lib/Makefile b/lib/Makefile
Patrick Williams92b42cb2022-09-03 06:53:57 -05002335index d9b1811f7506..4aa3e2ed2a7e 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002336--- a/lib/Makefile
2337+++ b/lib/Makefile
2338@@ -9,6 +9,7 @@ obj-$(CONFIG_EFI) += efi/
2339 obj-$(CONFIG_EFI_LOADER) += efi_driver/
2340 obj-$(CONFIG_EFI_LOADER) += efi_loader/
2341 obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/
2342+obj-$(CONFIG_ARM_FFA_TRANSPORT_HELPERS) += arm-ffa/
2343 obj-$(CONFIG_LZMA) += lzma/
2344 obj-$(CONFIG_BZIP2) += bzip2/
2345 obj-$(CONFIG_TIZEN) += tizen/
2346diff --git a/lib/arm-ffa/Kconfig b/lib/arm-ffa/Kconfig
2347new file mode 100644
2348index 000000000000..79acbc5a8fe3
2349--- /dev/null
2350+++ b/lib/arm-ffa/Kconfig
2351@@ -0,0 +1,6 @@
2352+config ARM_FFA_TRANSPORT_HELPERS
2353+ bool "Enable interface helpers for Arm Firmware Framework for Armv8-A"
2354+ depends on ARM_FFA_TRANSPORT
2355+ help
2356+ User layers call FF-A interfaces using helper functions which
2357+ pass the data and the FF-A function ID to the low level driver
2358diff --git a/lib/arm-ffa/Makefile b/lib/arm-ffa/Makefile
2359new file mode 100644
2360index 000000000000..c30c0f398126
2361--- /dev/null
2362+++ b/lib/arm-ffa/Makefile
2363@@ -0,0 +1,8 @@
2364+# SPDX-License-Identifier: GPL-2.0+
2365+#
2366+# (C) Copyright 2021 Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
2367+#
2368+
2369+# This file only gets included when CONFIG_ARM_FFA_TRANSPORT_HELPERS is set
2370+
2371+obj-y += arm_ffa_helper.o
2372diff --git a/lib/arm-ffa/arm_ffa_helper.c b/lib/arm-ffa/arm_ffa_helper.c
2373new file mode 100644
2374index 000000000000..623899d38044
2375--- /dev/null
2376+++ b/lib/arm-ffa/arm_ffa_helper.c
2377@@ -0,0 +1,188 @@
2378+// SPDX-License-Identifier: GPL-2.0+
2379+/*
2380+ * (C) Copyright 2021 ARM Limited
2381+ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
2382+ */
2383+
2384+#include <common.h>
2385+#include <arm_ffa_helper.h>
2386+#include <uuid.h>
2387+
2388+/**
2389+ * ffa_helper_get_partitions_info - Wrapper function for FFA_PARTITION_INFO_GET
2390+ *
2391+ * @func_data: Pointer to the FF-A function arguments container
2392+ * structure.
2393+ * The passed arguments:
2394+ * Mode 1: When getting from the driver the number of
2395+ * secure partitions:
2396+ * @data0_size: UUID size
2397+ * @data0: pointer to the UUID (little endian)
2398+ * @data1_size: size of the number of partitions
2399+ * variable
2400+ * @data1: pointer to the number of partitions
2401+ * variable. The variable will be set
2402+ * by the driver
2403+ * Mode 2: When requesting the driver to return the
2404+ * partitions information:
2405+ * @data0_size: UUID size
2406+ * @data0: pointer to the UUID (little endian)
2407+ * @data1_size: size of the SPs information buffer
2408+ * @data1: pointer to SPs information buffer
2409+ * (allocated by the client).
2410+ * The buffer will be filled by the driver
2411+ *
2412+ * This is the boot time function used by clients who wants to get from secure
2413+ * world the partition(s) information.
2414+ *
2415+ * A client of the FF-A driver should know the UUID of the service it wants to
2416+ * access. It should use the UUID to request the FF-A driver to provide the
2417+ * partition(s) information of the service. The client should use
2418+ * ffa_helper_get_partitions_info to pass the UUID information to the driver
2419+ * which uses PARTITION_INFO_GET to obtain the partition(s) information.
2420+ *
2421+ * ffa_helper_get_partitions_info should be called twice. First call is to get
2422+ * from the driver the number of secure partitions (SPs) associated to a
2423+ * particular UUID. Then, the caller (client) allocates the buffer to host the
2424+ * SPs data and issues a 2nd call. Then, the driver fills the SPs data in the
2425+ * pre-allocated buffer.
2426+ *
2427+ * Return:
2428+ *
2429+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
2430+ */
2431+int ffa_helper_get_partitions_info(struct ffa_interface_data *func_data)
2432+{
2433+ return ffa_get_invoke_func(FFA_PARTITION_INFO_GET, func_data);
2434+}
2435+
2436+/**
2437+ * ffa_helper_unmap_rxtx_buffers - Wrapper function for FFA_RXTX_UNMAP
2438+ *
2439+ * This is the boot time function that allows clients to unmap the RX/TX
2440+ * buffers
2441+ *
2442+ * Return:
2443+ *
2444+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
2445+ */
2446+int ffa_helper_unmap_rxtx_buffers(void)
2447+{
2448+ return ffa_get_invoke_func(FFA_RXTX_UNMAP, NULL);
2449+}
2450+
2451+/**
2452+ * ffa_helper_msg_send_direct_req - Wrapper function for
2453+ * FFA_MSG_SEND_DIRECT_{REQ,RESP}
2454+ * @func_data: Pointer to the FF-A function arguments container structure.
2455+ * The passed arguments:
2456+ * @data0_size: partition ID size
2457+ * @data0: pointer to the partition ID
2458+ * @data1_size: exchanged data size
2459+ * @data1: pointer to the data buffer preallocated by the client (in/out)
2460+ *
2461+ * This is the runtime function that allows clients to send data to the secure
2462+ * world partitions. The arm_ffa driver uses FFA_MSG_SEND_DIRECT_REQ to send the
2463+ * data to the secure partition. The response from the secure partition is
2464+ * handled internally by the driver using FFA_MSG_SEND_DIRECT_RESP and returned
2465+ * to ffa_helper_msg_send_direct_req through @func_data
2466+ *
2467+ * The maximum size of the data that can be exchanged is 20 bytes which is
2468+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
2469+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
2470+ *
2471+ * The client should pre-allocate a buffer pointed by @data1 which the size
2472+ * is sizeof(struct ffa_send_direct_data)
2473+ *
2474+ * Return:
2475+ *
2476+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
2477+ */
2478+int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data
2479+ *func_data)
2480+{
2481+ return ffa_get_invoke_func(FFA_MSG_SEND_DIRECT_REQ, func_data);
2482+}
2483+
2484+/**
2485+ * ffa_helper_init_device - Wrapper function for probing the arm_ffa device
2486+ *
2487+ * This boot time function should be called to probe the arm_ffa device so
2488+ * it becomes ready for use.
2489+ * To achieve that, this function is called automatically at initcalls
2490+ * level (after u-boot relocation).
2491+ *
2492+ * Return:
2493+ *
2494+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
2495+ */
2496+int ffa_helper_init_device(void)
2497+{
2498+ return ffa_init_device();
2499+}
2500+
2501+/**
2502+ * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer
2503+ * @uuid_str: UUID string in big endian format (36 bytes wide + '/0')
2504+ * @uuid_bin: preallocated 16 bytes UUID buffer in little endian format
2505+ *
2506+ * UUID binary format used by the FF-A framework (16 bytes):
2507+ *
2508+ * [LSB] 4B-2B-2B-2B-6B (little endian data fields)
2509+ *
2510+ * UUID string is 36 length of characters (36 bytes):
2511+ *
2512+ * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
2513+ * be be be be be
2514+ *
2515+ * where x is a hexadecimal character. Fields are separated by '-'s.
2516+ * When converting to a binary UUID, these endianness rules apply:
2517+ * be: means the field in the string is considered a big endian hex number
2518+ * and should be converted to little endian binary format
2519+ *
2520+ * Return:
2521+ *
2522+ * uuid_bin filled with little endian UUID data
2523+ * On success 0 is returned. Otherwise, failure code.
2524+ */
2525+int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin)
2526+{
2527+ u16 tmp16 = 0;
2528+ u32 tmp32 = 0;
2529+ u64 tmp64 = 0;
2530+
2531+ if (!uuid_str_valid(uuid_str) || !uuid_bin)
2532+ return -EINVAL;
2533+
2534+ /*
2535+ * reverse bytes from big to little endian
2536+ */
2537+ tmp32 = simple_strtoul(uuid_str, NULL, 16);
2538+ memcpy(uuid_bin, &tmp32, 4);
2539+
2540+ /*
2541+ * reverse bytes from big to little endian
2542+ */
2543+ tmp16 = simple_strtoul(uuid_str + 9, NULL, 16);
2544+ memcpy(uuid_bin + 4, &tmp16, 2);
2545+
2546+ /*
2547+ * reverse bytes from big to little endian
2548+ */
2549+ tmp16 = simple_strtoul(uuid_str + 14, NULL, 16);
2550+ memcpy(uuid_bin + 6, &tmp16, 2);
2551+
2552+ /*
2553+ * reverse bytes from big to little endian
2554+ */
2555+ tmp16 = simple_strtoul(uuid_str + 19, NULL, 16);
2556+ memcpy(uuid_bin + 8, &tmp16, 2);
2557+
2558+ /*
2559+ * reverse bytes from big to little endian
2560+ */
2561+ tmp64 = simple_strtoull(uuid_str + 24, NULL, 16);
2562+ memcpy(uuid_bin + 10, (char *)&tmp64, 6);
2563+
2564+ return 0;
2565+}
2566diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
Patrick Williams92b42cb2022-09-03 06:53:57 -05002567index 4da64b5d2962..c68d9ed4f0bd 100644
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002568--- a/lib/efi_loader/efi_boottime.c
2569+++ b/lib/efi_loader/efi_boottime.c
2570@@ -23,6 +23,10 @@
2571 #include <asm/setjmp.h>
2572 #include <linux/libfdt_env.h>
2573
2574+#if defined(CONFIG_ARM_FFA_TRANSPORT)
2575+#include <arm_ffa_helper.h>
2576+#endif
2577+
2578 DECLARE_GLOBAL_DATA_PTR;
2579
2580 /* Task priority level */
Patrick Williams92b42cb2022-09-03 06:53:57 -05002581@@ -2113,6 +2117,10 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002582 struct efi_event *evt, *next_event;
2583 efi_status_t ret = EFI_SUCCESS;
2584
2585+#if defined(CONFIG_ARM_FFA_TRANSPORT)
2586+ int ffa_ret;
2587+#endif
2588+
2589 EFI_ENTRY("%p, %zx", image_handle, map_key);
2590
2591 /* Check that the caller has read the current memory map */
Patrick Williams92b42cb2022-09-03 06:53:57 -05002592@@ -2173,6 +2181,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002593 dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
2594 }
2595
2596+#if defined(CONFIG_ARM_FFA_TRANSPORT)
2597+ /* unmap FF-A RX/TX buffers */
2598+ ffa_ret = ffa_helper_unmap_rxtx_buffers();
2599+ if (ffa_ret)
2600+ debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n");
2601+ else
2602+ debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n");
2603+#endif
2604+
2605 /* Patch out unsupported runtime function */
2606 efi_runtime_detach();
2607
2608--
Patrick Williams92b42cb2022-09-03 06:53:57 -050026092.37.1
Brad Bishopbec4ebc2022-08-03 09:55:16 -04002610