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