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