mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	arm_ffa: introduce sandbox FF-A support
Emulate Secure World's FF-A ABIs and allow testing U-Boot FF-A support Features of the sandbox FF-A support: - Introduce an FF-A emulator - Introduce an FF-A device driver for FF-A comms with emulated Secure World - Provides test methods allowing to read the status of the inspected ABIs The sandbox FF-A emulator supports only 64-bit direct messaging. Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> Reviewed-by: Simon Glass <sjg@chromium.org> Cc: Tom Rini <trini@konsulko.com> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org> Cc: Jens Wiklander <jens.wiklander@linaro.org> Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
		
							parent
							
								
									39d383bdac
								
							
						
					
					
						commit
						a09852d862
					
				@ -269,10 +269,11 @@ F:	configs/cortina_presidio-asic-pnand_defconfig
 | 
			
		||||
ARM FF-A
 | 
			
		||||
M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 | 
			
		||||
S:	Maintained
 | 
			
		||||
F:	arch/sandbox/include/asm/sandbox_arm_ffa.h
 | 
			
		||||
F:	arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
 | 
			
		||||
F:	doc/arch/arm64.ffa.rst
 | 
			
		||||
F:	drivers/firmware/arm-ffa/
 | 
			
		||||
F:	include/arm_ffa.h
 | 
			
		||||
F:	include/sandbox_arm_ffa.h
 | 
			
		||||
 | 
			
		||||
ARM FREESCALE IMX
 | 
			
		||||
M:	Stefano Babic <sbabic@denx.de>
 | 
			
		||||
 | 
			
		||||
@ -451,6 +451,15 @@
 | 
			
		||||
	thermal {
 | 
			
		||||
		compatible = "sandbox,thermal";
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	arm-ffa-emul {
 | 
			
		||||
		compatible = "sandbox,arm-ffa-emul";
 | 
			
		||||
 | 
			
		||||
		sandbox-arm-ffa {
 | 
			
		||||
				compatible = "sandbox,arm-ffa";
 | 
			
		||||
		};
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
&cros_ec {
 | 
			
		||||
 | 
			
		||||
@ -1831,6 +1831,14 @@
 | 
			
		||||
	extcon {
 | 
			
		||||
		compatible = "sandbox,extcon";
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	arm-ffa-emul {
 | 
			
		||||
		compatible = "sandbox,arm-ffa-emul";
 | 
			
		||||
 | 
			
		||||
		sandbox-arm-ffa {
 | 
			
		||||
				compatible = "sandbox,arm-ffa";
 | 
			
		||||
		};
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#include "sandbox_pmic.dtsi"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										72
									
								
								arch/sandbox/include/asm/sandbox_arm_ffa.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								arch/sandbox/include/asm/sandbox_arm_ffa.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0+ */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 | 
			
		||||
 *
 | 
			
		||||
 * Authors:
 | 
			
		||||
 *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SANDBOX_ARM_FFA_H
 | 
			
		||||
#define __SANDBOX_ARM_FFA_H
 | 
			
		||||
 | 
			
		||||
#include <arm_ffa.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This header provides public sandbox FF-A emulator declarations
 | 
			
		||||
 * and declarations needed by FF-A sandbox clients
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* UUIDs strings of the emulated services */
 | 
			
		||||
#define SANDBOX_SERVICE1_UUID	"ed32d533-4209-99e6-2d72-cdd998a79cc0"
 | 
			
		||||
#define SANDBOX_SERVICE2_UUID	"ed32d544-4209-99e6-2d72-cdd998a79cc0"
 | 
			
		||||
 | 
			
		||||
/* IDs of the emulated secure partitions (SPs) */
 | 
			
		||||
#define SANDBOX_SP1_ID 0x1245
 | 
			
		||||
#define SANDBOX_SP2_ID 0x9836
 | 
			
		||||
#define SANDBOX_SP3_ID 0x6452
 | 
			
		||||
#define SANDBOX_SP4_ID 0x7814
 | 
			
		||||
 | 
			
		||||
/* Invalid service UUID (no matching SP) */
 | 
			
		||||
#define SANDBOX_SERVICE3_UUID	"55d532ed-0942-e699-722d-c09ca798d9cd"
 | 
			
		||||
 | 
			
		||||
/* Invalid service UUID (invalid UUID string format) */
 | 
			
		||||
#define SANDBOX_SERVICE4_UUID	"32ed-0942-e699-722d-c09ca798d9cd"
 | 
			
		||||
 | 
			
		||||
/* Number of valid services */
 | 
			
		||||
#define SANDBOX_SP_COUNT_PER_VALID_SERVICE	2
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct ffa_sandbox_data - query ABI state data structure
 | 
			
		||||
 * @data0_size:	size of the first argument
 | 
			
		||||
 * @data0:	pointer to the first argument
 | 
			
		||||
 * @data1_size>:	size of the second argument
 | 
			
		||||
 * @data1:	pointer to the second argument
 | 
			
		||||
 *
 | 
			
		||||
 * Used to pass various types of data with different sizes between
 | 
			
		||||
 * the test cases and the sandbox emulator.
 | 
			
		||||
 * The data is for querying FF-A ABIs state.
 | 
			
		||||
 */
 | 
			
		||||
struct ffa_sandbox_data {
 | 
			
		||||
	u32 data0_size; /* size of the first argument */
 | 
			
		||||
	void *data0; /* pointer to the first argument */
 | 
			
		||||
	u32 data1_size; /* size of the second argument */
 | 
			
		||||
	void *data1; /* pointer to the second argument */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* The sandbox FF-A  emulator public functions */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_query_ffa_emul_state() - Inspect the FF-A ABIs
 | 
			
		||||
 * @queried_func_id:	The FF-A function to be queried
 | 
			
		||||
 * @func_data:  Pointer to the FF-A function arguments container structure
 | 
			
		||||
 *
 | 
			
		||||
 * Query the status of FF-A ABI specified in the input argument.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
int sandbox_query_ffa_emul_state(u32 queried_func_id,
 | 
			
		||||
				 struct ffa_sandbox_data *func_data);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										121
									
								
								arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,121 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0+ */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 | 
			
		||||
 *
 | 
			
		||||
 * Authors:
 | 
			
		||||
 *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SANDBOX_ARM_FFA_PRV_H
 | 
			
		||||
#define __SANDBOX_ARM_FFA_PRV_H
 | 
			
		||||
 | 
			
		||||
#include <arm_ffa_priv.h>
 | 
			
		||||
 | 
			
		||||
/* This header is exclusively used by the Sandbox FF-A driver and emulator */
 | 
			
		||||
 | 
			
		||||
/* Non-secure physical FF-A instance */
 | 
			
		||||
#define NS_PHYS_ENDPOINT_ID (0)
 | 
			
		||||
 | 
			
		||||
#define GET_NS_PHYS_ENDPOINT_ID_MASK		GENMASK(31, 16)
 | 
			
		||||
#define GET_NS_PHYS_ENDPOINT_ID(x)		\
 | 
			
		||||
			((u16)(FIELD_GET(GET_NS_PHYS_ENDPOINT_ID_MASK, (x))))
 | 
			
		||||
 | 
			
		||||
/* Helper macro for reading the destination partition ID */
 | 
			
		||||
#define GET_DST_SP_ID_MASK		GENMASK(15, 0)
 | 
			
		||||
#define GET_DST_SP_ID(x)		\
 | 
			
		||||
			((u16)(FIELD_GET(GET_DST_SP_ID_MASK, (x))))
 | 
			
		||||
 | 
			
		||||
/* Helper macro for setting the source partition ID */
 | 
			
		||||
#define PREP_SRC_SP_ID_MASK		GENMASK(31, 16)
 | 
			
		||||
#define PREP_SRC_SP_ID(x)		\
 | 
			
		||||
			(FIELD_PREP(PREP_SRC_SP_ID_MASK, (x)))
 | 
			
		||||
 | 
			
		||||
/* Helper macro for setting the destination endpoint ID */
 | 
			
		||||
#define PREP_NS_PHYS_ENDPOINT_ID_MASK		GENMASK(15, 0)
 | 
			
		||||
#define PREP_NS_PHYS_ENDPOINT_ID(x)		\
 | 
			
		||||
			(FIELD_PREP(PREP_NS_PHYS_ENDPOINT_ID_MASK, (x)))
 | 
			
		||||
 | 
			
		||||
/*  RX/TX buffers minimum size */
 | 
			
		||||
#define RXTX_BUFFERS_MIN_SIZE (RXTX_4K)
 | 
			
		||||
#define RXTX_BUFFERS_MIN_PAGES (1)
 | 
			
		||||
 | 
			
		||||
/* MBZ registers info */
 | 
			
		||||
 | 
			
		||||
/* x1-x7 MBZ */
 | 
			
		||||
#define FFA_X1X7_MBZ_CNT (7)
 | 
			
		||||
#define FFA_X1X7_MBZ_REG_START (&res->a1)
 | 
			
		||||
 | 
			
		||||
/* x4-x7 MBZ */
 | 
			
		||||
#define FFA_X4X7_MBZ_CNT (4)
 | 
			
		||||
#define FFA_X4X7_MBZ_REG_START (&res->a4)
 | 
			
		||||
 | 
			
		||||
/* x3-x7 MBZ */
 | 
			
		||||
#define FFA_X3X7_MBZ_CNT (5)
 | 
			
		||||
#define FFA_X3_MBZ_REG_START (&res->a3)
 | 
			
		||||
 | 
			
		||||
/* number of emulated FF-A secure partitions (SPs) */
 | 
			
		||||
#define SANDBOX_PARTITIONS_CNT (4)
 | 
			
		||||
 | 
			
		||||
/* Binary data of the emulated services UUIDs */
 | 
			
		||||
 | 
			
		||||
/* service 1  UUID binary data (little-endian format) */
 | 
			
		||||
#define SANDBOX_SERVICE1_UUID_A1	0xed32d533
 | 
			
		||||
#define SANDBOX_SERVICE1_UUID_A2	0x99e64209
 | 
			
		||||
#define SANDBOX_SERVICE1_UUID_A3	0x9cc02d72
 | 
			
		||||
#define SANDBOX_SERVICE1_UUID_A4	0xcdd998a7
 | 
			
		||||
 | 
			
		||||
/* service 2  UUID binary data (little-endian format) */
 | 
			
		||||
#define SANDBOX_SERVICE2_UUID_A1	0xed32d544
 | 
			
		||||
#define SANDBOX_SERVICE2_UUID_A2	0x99e64209
 | 
			
		||||
#define SANDBOX_SERVICE2_UUID_A3	0x9cc02d72
 | 
			
		||||
#define SANDBOX_SERVICE2_UUID_A4	0xcdd998a7
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct ffa_rxtxpair_info - structure hosting the RX/TX buffers flags
 | 
			
		||||
 * @rxbuf_owned:	RX buffer ownership flag (the owner is non secure world)
 | 
			
		||||
 * @rxbuf_mapped:	RX buffer mapping flag
 | 
			
		||||
 * @txbuf_owned	TX buffer ownership flag
 | 
			
		||||
 * @txbuf_mapped:	TX buffer mapping flag
 | 
			
		||||
 * @rxtx_buf_size:	RX/TX buffers size
 | 
			
		||||
 *
 | 
			
		||||
 * Hosts the ownership/mapping flags of the RX/TX buffers
 | 
			
		||||
 * When a buffer is owned/mapped its corresponding flag is set to 1 otherwise 0.
 | 
			
		||||
 */
 | 
			
		||||
struct ffa_rxtxpair_info {
 | 
			
		||||
	u8 rxbuf_owned;
 | 
			
		||||
	u8 rxbuf_mapped;
 | 
			
		||||
	u8 txbuf_owned;
 | 
			
		||||
	u8 txbuf_mapped;
 | 
			
		||||
	u32 rxtx_buf_size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct sandbox_ffa_emul - emulator data
 | 
			
		||||
 *
 | 
			
		||||
 * @fwk_version:	FF-A framework version
 | 
			
		||||
 * @id:	u-boot endpoint ID
 | 
			
		||||
 * @partitions:	The partitions descriptors structure
 | 
			
		||||
 * @pair:	The RX/TX buffers pair
 | 
			
		||||
 * @pair_info:	The RX/TX buffers pair flags and size
 | 
			
		||||
 * @test_ffa_data:	The data of the FF-A bus under test
 | 
			
		||||
 *
 | 
			
		||||
 * Hosts all the emulated secure world data.
 | 
			
		||||
 */
 | 
			
		||||
struct sandbox_ffa_emul {
 | 
			
		||||
	u32 fwk_version;
 | 
			
		||||
	u16 id;
 | 
			
		||||
	struct ffa_partitions partitions;
 | 
			
		||||
	struct ffa_rxtxpair pair;
 | 
			
		||||
	struct ffa_rxtxpair_info pair_info;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ffa_emul_find() - Finds the FF-A emulator
 | 
			
		||||
 * @dev:	the sandbox FF-A device (sandbox-arm-ffa)
 | 
			
		||||
 * @emulp:	the FF-A emulator device (sandbox-ffa-emul)
 | 
			
		||||
 * Return:
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
int ffa_emul_find(struct udevice *dev, struct udevice **emulp);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -260,3 +260,4 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
 | 
			
		||||
CONFIG_UNIT_TEST=y
 | 
			
		||||
CONFIG_UT_TIME=y
 | 
			
		||||
CONFIG_UT_DM=y
 | 
			
		||||
CONFIG_ARM_FFA_TRANSPORT=y
 | 
			
		||||
 | 
			
		||||
@ -345,3 +345,4 @@ CONFIG_TEST_FDTDEC=y
 | 
			
		||||
CONFIG_UNIT_TEST=y
 | 
			
		||||
CONFIG_UT_TIME=y
 | 
			
		||||
CONFIG_UT_DM=y
 | 
			
		||||
CONFIG_ARM_FFA_TRANSPORT=y
 | 
			
		||||
 | 
			
		||||
@ -33,6 +33,10 @@ The U-Boot FF-A support provides the following parts:
 | 
			
		||||
 | 
			
		||||
- A Uclass driver providing generic FF-A methods.
 | 
			
		||||
- An Arm FF-A device driver providing Arm-specific methods and reusing the Uclass methods.
 | 
			
		||||
- A sandbox emulator for Arm FF-A, emulates the FF-A side of the Secure World and provides
 | 
			
		||||
  FF-A ABIs inspection methods.
 | 
			
		||||
- An FF-A sandbox device driver for FF-A communication with the emulated Secure World.
 | 
			
		||||
  The driver leverages the FF-A Uclass to establish FF-A communication.
 | 
			
		||||
 | 
			
		||||
FF-A and SMC specifications
 | 
			
		||||
-------------------------------------------
 | 
			
		||||
@ -62,6 +66,7 @@ CONFIG_ARM_FFA_TRANSPORT
 | 
			
		||||
    Enables the FF-A support. Turn this on if you want to use FF-A
 | 
			
		||||
    communication.
 | 
			
		||||
    When using an Arm 64-bit platform, the Arm FF-A driver will be used.
 | 
			
		||||
    When using sandbox, the sandbox FF-A emulator and FF-A sandbox driver will be used.
 | 
			
		||||
 | 
			
		||||
FF-A ABIs under the hood
 | 
			
		||||
---------------------------------------
 | 
			
		||||
@ -98,10 +103,8 @@ architecture features including FF-A bus.
 | 
			
		||||
 | 
			
		||||
    Class     Index  Probed  Driver                Name
 | 
			
		||||
   -----------------------------------------------------------
 | 
			
		||||
   ...
 | 
			
		||||
    firmware      0  [ + ]   psci                      |-- psci
 | 
			
		||||
    ffa                   0  [   ]   arm_ffa               |   `-- arm_ffa
 | 
			
		||||
   ...
 | 
			
		||||
 | 
			
		||||
The PSCI driver is bound to the PSCI device and when probed it tries to discover
 | 
			
		||||
the architecture features by calling a callback the features drivers provide.
 | 
			
		||||
@ -203,6 +206,18 @@ The following features are provided:
 | 
			
		||||
 | 
			
		||||
- FF-A bus can be compiled and used without EFI
 | 
			
		||||
 | 
			
		||||
Relationship between the sandbox emulator and the FF-A device
 | 
			
		||||
---------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
::
 | 
			
		||||
 | 
			
		||||
   => dm tree
 | 
			
		||||
 | 
			
		||||
    Class     Index  Probed  Driver                Name
 | 
			
		||||
   -----------------------------------------------------------
 | 
			
		||||
   ffa_emul      0  [ + ]   sandbox_ffa_emul      `-- arm-ffa-emul
 | 
			
		||||
    ffa                  0  [    ]   sandbox_arm_ffa               `-- sandbox-arm-ffa
 | 
			
		||||
 | 
			
		||||
Example of boot logs with FF-A enabled
 | 
			
		||||
--------------------------------------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -200,6 +200,7 @@ Supported Drivers
 | 
			
		||||
 | 
			
		||||
U-Boot sandbox supports these emulations:
 | 
			
		||||
 | 
			
		||||
- Arm FF-A
 | 
			
		||||
- Block devices
 | 
			
		||||
- Chrome OS EC
 | 
			
		||||
- GPIO
 | 
			
		||||
 | 
			
		||||
@ -2,9 +2,9 @@
 | 
			
		||||
 | 
			
		||||
config ARM_FFA_TRANSPORT
 | 
			
		||||
	bool "Enable Arm Firmware Framework for Armv8-A driver"
 | 
			
		||||
	depends on DM && ARM64
 | 
			
		||||
	select ARM_SMCCC
 | 
			
		||||
	select ARM_SMCCC_FEATURES
 | 
			
		||||
	depends on DM && (ARM64 || SANDBOX)
 | 
			
		||||
	select ARM_SMCCC if !SANDBOX
 | 
			
		||||
	select ARM_SMCCC_FEATURES if !SANDBOX
 | 
			
		||||
	select LIB_UUID
 | 
			
		||||
	select DEVRES
 | 
			
		||||
	help
 | 
			
		||||
@ -32,5 +32,10 @@ config ARM_FFA_TRANSPORT
 | 
			
		||||
	  Generic FF-A methods are implemented in the Uclass (arm-ffa-uclass.c).
 | 
			
		||||
	  Arm specific methods are implemented in the Arm driver (arm-ffa.c).
 | 
			
		||||
 | 
			
		||||
	  For more details about the FF-A support, please refer to doc/arch/arm64.ffa.rst
 | 
			
		||||
	  FF-A sandbox is provided to run FF-A under sandbox and allows to test the FF-A Uclass.
 | 
			
		||||
	  Sandbox support includes an emulator for Arm FF-A which emulates the FF-A side of
 | 
			
		||||
	  the Secure World and provides FF-A ABIs inspection methods (ffa-emul-uclass.c).
 | 
			
		||||
	  An FF-A sandbox driver is also provided for FF-A communication with the emulated
 | 
			
		||||
	  Secure World (sandbox_ffa.c).
 | 
			
		||||
 | 
			
		||||
	  For more details about the FF-A support, please refer to doc/arch/arm64.ffa.rst
 | 
			
		||||
 | 
			
		||||
@ -5,4 +5,12 @@
 | 
			
		||||
# Authors:
 | 
			
		||||
#   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 | 
			
		||||
 | 
			
		||||
obj-y += arm-ffa-uclass.o arm-ffa.o
 | 
			
		||||
# build the generic FF-A methods
 | 
			
		||||
obj-y += arm-ffa-uclass.o
 | 
			
		||||
ifeq ($(CONFIG_SANDBOX),y)
 | 
			
		||||
# build the FF-A sandbox emulator and driver
 | 
			
		||||
obj-y += ffa-emul-uclass.o sandbox_ffa.o
 | 
			
		||||
else
 | 
			
		||||
# build the Arm64 FF-A driver
 | 
			
		||||
obj-y += arm-ffa.o
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										720
									
								
								drivers/firmware/arm-ffa/ffa-emul-uclass.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										720
									
								
								drivers/firmware/arm-ffa/ffa-emul-uclass.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,720 @@
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0+
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 | 
			
		||||
 *
 | 
			
		||||
 * Authors:
 | 
			
		||||
 *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 | 
			
		||||
 */
 | 
			
		||||
#include <common.h>
 | 
			
		||||
#include <dm.h>
 | 
			
		||||
#include <mapmem.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <asm/global_data.h>
 | 
			
		||||
#include <asm/sandbox_arm_ffa.h>
 | 
			
		||||
#include <asm/sandbox_arm_ffa_priv.h>
 | 
			
		||||
#include <dm/device-internal.h>
 | 
			
		||||
#include <dm/lists.h>
 | 
			
		||||
#include <dm/root.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/sizes.h>
 | 
			
		||||
 | 
			
		||||
DECLARE_GLOBAL_DATA_PTR;
 | 
			
		||||
 | 
			
		||||
/* The partitions (SPs) table */
 | 
			
		||||
static struct ffa_partition_desc sandbox_partitions[SANDBOX_PARTITIONS_CNT] = {
 | 
			
		||||
	{
 | 
			
		||||
		.info = { .id = SANDBOX_SP1_ID, .exec_ctxt = 0x5687, .properties = 0x89325621 },
 | 
			
		||||
		.sp_uuid = {
 | 
			
		||||
			.a1 = SANDBOX_SERVICE1_UUID_A1,
 | 
			
		||||
			.a2 = SANDBOX_SERVICE1_UUID_A2,
 | 
			
		||||
			.a3 = SANDBOX_SERVICE1_UUID_A3,
 | 
			
		||||
			.a4 = SANDBOX_SERVICE1_UUID_A4,
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		.info = { .id = SANDBOX_SP3_ID, .exec_ctxt = 0x7687, .properties = 0x23325621 },
 | 
			
		||||
		.sp_uuid = {
 | 
			
		||||
			.a1 = SANDBOX_SERVICE2_UUID_A1,
 | 
			
		||||
			.a2 = SANDBOX_SERVICE2_UUID_A2,
 | 
			
		||||
			.a3 = SANDBOX_SERVICE2_UUID_A3,
 | 
			
		||||
			.a4 = SANDBOX_SERVICE2_UUID_A4,
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		.info = { .id = SANDBOX_SP2_ID, .exec_ctxt = 0x9587, .properties = 0x45325621 },
 | 
			
		||||
		.sp_uuid = {
 | 
			
		||||
			.a1 = SANDBOX_SERVICE1_UUID_A1,
 | 
			
		||||
			.a2 = SANDBOX_SERVICE1_UUID_A2,
 | 
			
		||||
			.a3 = SANDBOX_SERVICE1_UUID_A3,
 | 
			
		||||
			.a4 = SANDBOX_SERVICE1_UUID_A4,
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		.info = { .id = SANDBOX_SP4_ID, .exec_ctxt = 0x1487, .properties = 0x70325621 },
 | 
			
		||||
		.sp_uuid = {
 | 
			
		||||
			.a1 = SANDBOX_SERVICE2_UUID_A1,
 | 
			
		||||
			.a2 = SANDBOX_SERVICE2_UUID_A2,
 | 
			
		||||
			.a3 = SANDBOX_SERVICE2_UUID_A3,
 | 
			
		||||
			.a4 = SANDBOX_SERVICE2_UUID_A4,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* The emulator functions */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_version() - Emulated FFA_VERSION handler function
 | 
			
		||||
 * @emul: The sandbox FF-A emulator device
 | 
			
		||||
 * @pargs: The SMC call input arguments a0-a7
 | 
			
		||||
 * @res:  The SMC return data
 | 
			
		||||
 *
 | 
			
		||||
 * Emulate FFA_VERSION FF-A function.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static int sandbox_ffa_version(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res)
 | 
			
		||||
{
 | 
			
		||||
	struct sandbox_ffa_emul *priv = dev_get_priv(emul);
 | 
			
		||||
 | 
			
		||||
	priv->fwk_version = FFA_VERSION_1_0;
 | 
			
		||||
	res->a0 = priv->fwk_version;
 | 
			
		||||
 | 
			
		||||
	/* x1-x7 MBZ */
 | 
			
		||||
	memset(FFA_X1X7_MBZ_REG_START, 0, FFA_X1X7_MBZ_CNT * sizeof(ulong));
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_id_get() - Emulated FFA_ID_GET handler function
 | 
			
		||||
 * @emul: The sandbox FF-A emulator device
 | 
			
		||||
 * @pargs: The SMC call input arguments a0-a7
 | 
			
		||||
 * @res:  The SMC return data
 | 
			
		||||
 *
 | 
			
		||||
 * Emulate FFA_ID_GET FF-A function.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_id_get(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res)
 | 
			
		||||
{
 | 
			
		||||
	struct sandbox_ffa_emul *priv = dev_get_priv(emul);
 | 
			
		||||
 | 
			
		||||
	res->a0 = FFA_SMC_32(FFA_SUCCESS);
 | 
			
		||||
	res->a1 = 0;
 | 
			
		||||
 | 
			
		||||
	priv->id = NS_PHYS_ENDPOINT_ID;
 | 
			
		||||
	res->a2 = priv->id;
 | 
			
		||||
 | 
			
		||||
	/* x3-x7 MBZ */
 | 
			
		||||
	memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_features() - Emulated FFA_FEATURES handler function
 | 
			
		||||
 * @pargs: The SMC call input arguments a0-a7
 | 
			
		||||
 * @res:  The SMC return data
 | 
			
		||||
 *
 | 
			
		||||
 * Emulate FFA_FEATURES FF-A function.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_features(ffa_value_t *pargs, ffa_value_t *res)
 | 
			
		||||
{
 | 
			
		||||
	res->a1 = 0;
 | 
			
		||||
 | 
			
		||||
	if (pargs->a1 == FFA_SMC_64(FFA_RXTX_MAP)) {
 | 
			
		||||
		res->a0 = FFA_SMC_32(FFA_SUCCESS);
 | 
			
		||||
		res->a2 = RXTX_BUFFERS_MIN_SIZE;
 | 
			
		||||
		res->a3 = 0;
 | 
			
		||||
		/* x4-x7 MBZ */
 | 
			
		||||
		memset(FFA_X4X7_MBZ_REG_START, 0, FFA_X4X7_MBZ_CNT * sizeof(ulong));
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res->a0 = FFA_SMC_32(FFA_ERROR);
 | 
			
		||||
	res->a2 = -NOT_SUPPORTED;
 | 
			
		||||
	/* x3-x7 MBZ */
 | 
			
		||||
	memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
 | 
			
		||||
	log_err("FF-A interface %lx not implemented\n", pargs->a1);
 | 
			
		||||
 | 
			
		||||
	return ffa_to_std_errmap[NOT_SUPPORTED];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_partition_info_get() - Emulated FFA_PARTITION_INFO_GET handler
 | 
			
		||||
 * @emul: The sandbox FF-A emulator device
 | 
			
		||||
 * @pargs: The SMC call input arguments a0-a7
 | 
			
		||||
 * @res:  The SMC return data
 | 
			
		||||
 *
 | 
			
		||||
 * Emulate FFA_PARTITION_INFO_GET FF-A function.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_partition_info_get(struct udevice *emul, ffa_value_t *pargs,
 | 
			
		||||
					  ffa_value_t *res)
 | 
			
		||||
{
 | 
			
		||||
	struct ffa_partition_info *rxbuf_desc_info = NULL;
 | 
			
		||||
	u32 descs_cnt;
 | 
			
		||||
	u32 descs_size_bytes;
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct sandbox_ffa_emul *priv = dev_get_priv(emul);
 | 
			
		||||
 | 
			
		||||
	res->a0 = FFA_SMC_32(FFA_ERROR);
 | 
			
		||||
 | 
			
		||||
	if (!priv->pair.rxbuf) {
 | 
			
		||||
		res->a2 = -DENIED;
 | 
			
		||||
		ret = ffa_to_std_errmap[DENIED];
 | 
			
		||||
		goto cleanup;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (priv->pair_info.rxbuf_owned) {
 | 
			
		||||
		res->a2 = -BUSY;
 | 
			
		||||
		ret = ffa_to_std_errmap[BUSY];
 | 
			
		||||
		goto cleanup;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!priv->partitions.descs) {
 | 
			
		||||
		priv->partitions.descs = sandbox_partitions;
 | 
			
		||||
		priv->partitions.count = SANDBOX_PARTITIONS_CNT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	descs_size_bytes = SANDBOX_PARTITIONS_CNT *
 | 
			
		||||
		sizeof(struct ffa_partition_desc);
 | 
			
		||||
 | 
			
		||||
	/* Abort if the RX buffer size is smaller than the descs buffer size */
 | 
			
		||||
	if ((priv->pair_info.rxtx_buf_size * SZ_4K) < descs_size_bytes) {
 | 
			
		||||
		res->a2 = -NO_MEMORY;
 | 
			
		||||
		ret = ffa_to_std_errmap[NO_MEMORY];
 | 
			
		||||
		goto cleanup;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rxbuf_desc_info = priv->pair.rxbuf;
 | 
			
		||||
 | 
			
		||||
	/* No UUID specified. Return the information of all partitions */
 | 
			
		||||
	if (!pargs->a1 && !pargs->a2 && !pargs->a3 && !pargs->a4) {
 | 
			
		||||
		for (descs_cnt = 0; descs_cnt < SANDBOX_PARTITIONS_CNT; descs_cnt++)
 | 
			
		||||
			*(rxbuf_desc_info++) = priv->partitions.descs[descs_cnt].info;
 | 
			
		||||
 | 
			
		||||
		res->a0 = FFA_SMC_32(FFA_SUCCESS);
 | 
			
		||||
		res->a2 = SANDBOX_PARTITIONS_CNT;
 | 
			
		||||
		/* Transfer ownership to the consumer: the non secure world */
 | 
			
		||||
		priv->pair_info.rxbuf_owned = 1;
 | 
			
		||||
		ret = 0;
 | 
			
		||||
 | 
			
		||||
		goto cleanup;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* A UUID specified. Return the info of all SPs matching the UUID */
 | 
			
		||||
 | 
			
		||||
	for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++)
 | 
			
		||||
		if (pargs->a1 == priv->partitions.descs[descs_cnt].sp_uuid.a1 &&
 | 
			
		||||
		    pargs->a2 == priv->partitions.descs[descs_cnt].sp_uuid.a2 &&
 | 
			
		||||
		    pargs->a3 == priv->partitions.descs[descs_cnt].sp_uuid.a3 &&
 | 
			
		||||
		    pargs->a4 == priv->partitions.descs[descs_cnt].sp_uuid.a4) {
 | 
			
		||||
			*(rxbuf_desc_info++) = priv->partitions.descs[descs_cnt].info;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if (rxbuf_desc_info != priv->pair.rxbuf) {
 | 
			
		||||
		res->a0 = FFA_SMC_32(FFA_SUCCESS);
 | 
			
		||||
		/* Store the partitions count */
 | 
			
		||||
		res->a2 = (ulong)
 | 
			
		||||
			(rxbuf_desc_info - (struct ffa_partition_info *)
 | 
			
		||||
			 priv->pair.rxbuf);
 | 
			
		||||
		ret = 0;
 | 
			
		||||
 | 
			
		||||
		/* Transfer ownership to the consumer: the non secure world */
 | 
			
		||||
		priv->pair_info.rxbuf_owned = 1;
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Unrecognized UUID */
 | 
			
		||||
		res->a2 = -INVALID_PARAMETERS;
 | 
			
		||||
		ret = ffa_to_std_errmap[INVALID_PARAMETERS];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
cleanup:
 | 
			
		||||
 | 
			
		||||
	log_err("FFA_PARTITION_INFO_GET (%ld)\n", res->a2);
 | 
			
		||||
 | 
			
		||||
	res->a1 = 0;
 | 
			
		||||
 | 
			
		||||
	/* x3-x7 MBZ */
 | 
			
		||||
	memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_rxtx_map() - Emulated FFA_RXTX_MAP handler
 | 
			
		||||
 * @emul: The sandbox FF-A emulator device
 | 
			
		||||
 * @pargs: The SMC call input arguments a0-a7
 | 
			
		||||
 * @res:  The SMC return data
 | 
			
		||||
 *
 | 
			
		||||
 * Emulate FFA_RXTX_MAP FF-A function.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_rxtx_map(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct sandbox_ffa_emul *priv = dev_get_priv(emul);
 | 
			
		||||
 | 
			
		||||
	res->a0 = FFA_SMC_32(FFA_ERROR);
 | 
			
		||||
 | 
			
		||||
	if (priv->pair.txbuf && priv->pair.rxbuf) {
 | 
			
		||||
		res->a2 = -DENIED;
 | 
			
		||||
		ret = ffa_to_std_errmap[DENIED];
 | 
			
		||||
		goto feedback;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pargs->a3 >= RXTX_BUFFERS_MIN_PAGES && pargs->a1 && pargs->a2) {
 | 
			
		||||
		priv->pair.txbuf = map_sysmem(pargs->a1, 0);
 | 
			
		||||
		priv->pair.rxbuf = map_sysmem(pargs->a2, 0);
 | 
			
		||||
		priv->pair_info.rxtx_buf_size = pargs->a3;
 | 
			
		||||
		priv->pair_info.rxbuf_mapped = 1;
 | 
			
		||||
		res->a0 = FFA_SMC_32(FFA_SUCCESS);
 | 
			
		||||
		res->a2 = 0;
 | 
			
		||||
		ret = 0;
 | 
			
		||||
		goto feedback;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!pargs->a1 || !pargs->a2) {
 | 
			
		||||
		res->a2 = -INVALID_PARAMETERS;
 | 
			
		||||
		ret = ffa_to_std_errmap[INVALID_PARAMETERS];
 | 
			
		||||
	} else {
 | 
			
		||||
		res->a2 = -NO_MEMORY;
 | 
			
		||||
		ret = ffa_to_std_errmap[NO_MEMORY];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_err("Error in FFA_RXTX_MAP arguments (%d)\n",
 | 
			
		||||
		(int)res->a2);
 | 
			
		||||
 | 
			
		||||
feedback:
 | 
			
		||||
 | 
			
		||||
	res->a1 = 0;
 | 
			
		||||
 | 
			
		||||
	/* x3-x7 MBZ */
 | 
			
		||||
	memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_rxtx_unmap() - Emulated FFA_RXTX_UNMAP handler
 | 
			
		||||
 * @emul: The sandbox FF-A emulator device
 | 
			
		||||
 * @pargs: The SMC call input arguments a0-a7
 | 
			
		||||
 * @res:  The SMC return data
 | 
			
		||||
 *
 | 
			
		||||
 * Emulate FFA_RXTX_UNMAP FF-A function.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_rxtx_unmap(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct sandbox_ffa_emul *priv = dev_get_priv(emul);
 | 
			
		||||
 | 
			
		||||
	res->a0 = FFA_SMC_32(FFA_ERROR);
 | 
			
		||||
	res->a2 = -INVALID_PARAMETERS;
 | 
			
		||||
	ret = ffa_to_std_errmap[INVALID_PARAMETERS];
 | 
			
		||||
 | 
			
		||||
	if (GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id)
 | 
			
		||||
		goto feedback;
 | 
			
		||||
 | 
			
		||||
	if (priv->pair.txbuf && priv->pair.rxbuf) {
 | 
			
		||||
		priv->pair.txbuf = 0;
 | 
			
		||||
		priv->pair.rxbuf = 0;
 | 
			
		||||
		priv->pair_info.rxtx_buf_size = 0;
 | 
			
		||||
		priv->pair_info.rxbuf_mapped = 0;
 | 
			
		||||
		res->a0 = FFA_SMC_32(FFA_SUCCESS);
 | 
			
		||||
		res->a2 = 0;
 | 
			
		||||
		ret = 0;
 | 
			
		||||
		goto feedback;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_err("No buffer pair registered on behalf of the caller\n");
 | 
			
		||||
 | 
			
		||||
feedback:
 | 
			
		||||
 | 
			
		||||
	res->a1 = 0;
 | 
			
		||||
 | 
			
		||||
	/* x3-x7 MBZ */
 | 
			
		||||
	memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_rx_release() - Emulated FFA_RX_RELEASE handler
 | 
			
		||||
 * @emul: The sandbox FF-A emulator device
 | 
			
		||||
 * @pargs: The SMC call input arguments a0-a7
 | 
			
		||||
 * @res:  The SMC return data
 | 
			
		||||
 *
 | 
			
		||||
 * Emulate FFA_RX_RELEASE FF-A function.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_rx_release(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct sandbox_ffa_emul *priv = dev_get_priv(emul);
 | 
			
		||||
 | 
			
		||||
	if (!priv->pair_info.rxbuf_owned) {
 | 
			
		||||
		res->a0 = FFA_SMC_32(FFA_ERROR);
 | 
			
		||||
		res->a2 = -DENIED;
 | 
			
		||||
		ret = ffa_to_std_errmap[DENIED];
 | 
			
		||||
	} else {
 | 
			
		||||
		priv->pair_info.rxbuf_owned = 0;
 | 
			
		||||
		res->a0 = FFA_SMC_32(FFA_SUCCESS);
 | 
			
		||||
		res->a2 = 0;
 | 
			
		||||
		ret = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res->a1 = 0;
 | 
			
		||||
 | 
			
		||||
	/* x3-x7 MBZ */
 | 
			
		||||
	memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_sp_valid() - Check SP validity
 | 
			
		||||
 * @emul: The sandbox FF-A emulator device
 | 
			
		||||
 * @part_id:	partition ID to check
 | 
			
		||||
 *
 | 
			
		||||
 * Search the input ID in the descriptors table.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 1 on success (Partition found). Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_sp_valid(struct udevice *emul, u16 part_id)
 | 
			
		||||
{
 | 
			
		||||
	u32 descs_cnt;
 | 
			
		||||
	struct sandbox_ffa_emul *priv = dev_get_priv(emul);
 | 
			
		||||
 | 
			
		||||
	for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++)
 | 
			
		||||
		if (priv->partitions.descs[descs_cnt].info.id == part_id)
 | 
			
		||||
			return 1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_msg_send_direct_req() - Emulated FFA_MSG_SEND_DIRECT_{REQ,RESP} handler
 | 
			
		||||
 * @emul: The sandbox FF-A emulator device
 | 
			
		||||
 * @pargs: The SMC call input arguments a0-a7
 | 
			
		||||
 * @res:  The SMC return data
 | 
			
		||||
 *
 | 
			
		||||
 * Emulate FFA_MSG_SEND_DIRECT_{REQ,RESP} FF-A ABIs.
 | 
			
		||||
 * Only SMC 64-bit is supported in Sandbox.
 | 
			
		||||
 *
 | 
			
		||||
 * Emulating interrupts is not supported. So, FFA_RUN and FFA_INTERRUPT are not
 | 
			
		||||
 * supported. In case of success FFA_MSG_SEND_DIRECT_RESP is returned with
 | 
			
		||||
 * default pattern data (0xff).
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_msg_send_direct_req(struct udevice *emul,
 | 
			
		||||
					   ffa_value_t *pargs, ffa_value_t *res)
 | 
			
		||||
{
 | 
			
		||||
	u16 part_id;
 | 
			
		||||
	struct sandbox_ffa_emul *priv = dev_get_priv(emul);
 | 
			
		||||
 | 
			
		||||
	part_id = GET_DST_SP_ID(pargs->a1);
 | 
			
		||||
 | 
			
		||||
	if (GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id ||
 | 
			
		||||
	    !sandbox_ffa_sp_valid(emul, part_id) || pargs->a2) {
 | 
			
		||||
		res->a0 = FFA_SMC_32(FFA_ERROR);
 | 
			
		||||
		res->a1 = 0;
 | 
			
		||||
		res->a2 = -INVALID_PARAMETERS;
 | 
			
		||||
 | 
			
		||||
		/* x3-x7 MBZ */
 | 
			
		||||
		memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
 | 
			
		||||
 | 
			
		||||
		return ffa_to_std_errmap[INVALID_PARAMETERS];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res->a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
 | 
			
		||||
 | 
			
		||||
	res->a1 = PREP_SRC_SP_ID(part_id) |
 | 
			
		||||
		PREP_NS_PHYS_ENDPOINT_ID(priv->id);
 | 
			
		||||
 | 
			
		||||
	res->a2 = 0;
 | 
			
		||||
 | 
			
		||||
	/* Return 0xff bytes as a response */
 | 
			
		||||
	res->a3 = -1UL;
 | 
			
		||||
	res->a4 = -1UL;
 | 
			
		||||
	res->a5 = -1UL;
 | 
			
		||||
	res->a6 = -1UL;
 | 
			
		||||
	res->a7 = -1UL;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_get_rxbuf_flags() - Read the mapping/ownership flags
 | 
			
		||||
 * @emul: The sandbox FF-A emulator device
 | 
			
		||||
 * @queried_func_id:	The FF-A function to be queried
 | 
			
		||||
 * @func_data:  Pointer to the FF-A function arguments container structure
 | 
			
		||||
 *
 | 
			
		||||
 * Query the status flags of the following emulated
 | 
			
		||||
 * ABIs: FFA_RXTX_MAP, FFA_RXTX_UNMAP, FFA_RX_RELEASE.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_get_rxbuf_flags(struct udevice *emul, u32 queried_func_id,
 | 
			
		||||
				       struct ffa_sandbox_data *func_data)
 | 
			
		||||
{
 | 
			
		||||
	struct sandbox_ffa_emul *priv = dev_get_priv(emul);
 | 
			
		||||
 | 
			
		||||
	if (!func_data)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	if (!func_data->data0 || func_data->data0_size != sizeof(u8))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	switch (queried_func_id) {
 | 
			
		||||
	case FFA_RXTX_MAP:
 | 
			
		||||
	case FFA_RXTX_UNMAP:
 | 
			
		||||
		*((u8 *)func_data->data0) = priv->pair_info.rxbuf_mapped;
 | 
			
		||||
		return 0;
 | 
			
		||||
	case FFA_RX_RELEASE:
 | 
			
		||||
		*((u8 *)func_data->data0) = priv->pair_info.rxbuf_owned;
 | 
			
		||||
		return 0;
 | 
			
		||||
	default:
 | 
			
		||||
		log_err("The querried FF-A interface flag (%d) undefined\n",
 | 
			
		||||
			queried_func_id);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_get_fwk_version() - Return the FFA framework version
 | 
			
		||||
 * @emul: The sandbox FF-A emulator device
 | 
			
		||||
 * @func_data:  Pointer to the FF-A function arguments container structure
 | 
			
		||||
 *
 | 
			
		||||
 * Return the FFA framework version read from the FF-A emulator data.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_get_fwk_version(struct udevice *emul, struct ffa_sandbox_data *func_data)
 | 
			
		||||
{
 | 
			
		||||
	struct sandbox_ffa_emul *priv = dev_get_priv(emul);
 | 
			
		||||
 | 
			
		||||
	if (!func_data)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	if (!func_data->data0 ||
 | 
			
		||||
	    func_data->data0_size != sizeof(priv->fwk_version))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	*((u32 *)func_data->data0) = priv->fwk_version;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_get_parts() - Return the address of partitions data
 | 
			
		||||
 * @emul: The sandbox FF-A emulator device
 | 
			
		||||
 * @func_data:  Pointer to the FF-A function arguments container structure
 | 
			
		||||
 *
 | 
			
		||||
 * Return the address of partitions data read from the FF-A emulator data.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_get_parts(struct udevice *emul, struct ffa_sandbox_data *func_data)
 | 
			
		||||
{
 | 
			
		||||
	struct sandbox_ffa_emul *priv = dev_get_priv(emul);
 | 
			
		||||
 | 
			
		||||
	if (!func_data)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	if (!func_data->data0 ||
 | 
			
		||||
	    func_data->data0_size != sizeof(struct ffa_partitions *))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	*((struct ffa_partitions **)func_data->data0) = &priv->partitions;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_query_ffa_emul_state() - Inspect the FF-A ABIs
 | 
			
		||||
 * @queried_func_id:	The FF-A function to be queried
 | 
			
		||||
 * @func_data:  Pointer to the FF-A function arguments container structure
 | 
			
		||||
 *
 | 
			
		||||
 * Query the status of FF-A ABI specified in the input argument.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
int sandbox_query_ffa_emul_state(u32 queried_func_id,
 | 
			
		||||
				 struct ffa_sandbox_data *func_data)
 | 
			
		||||
{
 | 
			
		||||
	struct udevice *emul;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = uclass_first_device_err(UCLASS_FFA_EMUL, &emul);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		log_err("Cannot find FF-A emulator during querying state\n");
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (queried_func_id) {
 | 
			
		||||
	case FFA_RXTX_MAP:
 | 
			
		||||
	case FFA_RXTX_UNMAP:
 | 
			
		||||
	case FFA_RX_RELEASE:
 | 
			
		||||
		return sandbox_ffa_get_rxbuf_flags(emul, queried_func_id, func_data);
 | 
			
		||||
	case FFA_VERSION:
 | 
			
		||||
		return sandbox_ffa_get_fwk_version(emul, func_data);
 | 
			
		||||
	case FFA_PARTITION_INFO_GET:
 | 
			
		||||
		return sandbox_ffa_get_parts(emul, func_data);
 | 
			
		||||
	default:
 | 
			
		||||
		log_err("Undefined FF-A interface (%d)\n",
 | 
			
		||||
			queried_func_id);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_arm_ffa_smccc_smc() - FF-A SMC call emulation
 | 
			
		||||
 * @args:	the SMC call arguments
 | 
			
		||||
 * @res:	the SMC call returned data
 | 
			
		||||
 *
 | 
			
		||||
 * Emulate the FF-A ABIs SMC call.
 | 
			
		||||
 * The emulated FF-A ABI is identified and invoked.
 | 
			
		||||
 * FF-A emulation is based on the FF-A specification 1.0
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure.
 | 
			
		||||
 * FF-A protocol error codes are returned using the registers arguments as
 | 
			
		||||
 * described by the specification
 | 
			
		||||
 */
 | 
			
		||||
void sandbox_arm_ffa_smccc_smc(ffa_value_t *args, ffa_value_t *res)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	struct udevice *emul;
 | 
			
		||||
 | 
			
		||||
	ret = uclass_first_device_err(UCLASS_FFA_EMUL, &emul);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		log_err("Cannot find FF-A emulator during SMC emulation\n");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (args->a0) {
 | 
			
		||||
	case FFA_SMC_32(FFA_VERSION):
 | 
			
		||||
		ret = sandbox_ffa_version(emul, args, res);
 | 
			
		||||
		break;
 | 
			
		||||
	case FFA_SMC_32(FFA_PARTITION_INFO_GET):
 | 
			
		||||
		ret = sandbox_ffa_partition_info_get(emul, args, res);
 | 
			
		||||
		break;
 | 
			
		||||
	case FFA_SMC_32(FFA_RXTX_UNMAP):
 | 
			
		||||
		ret = sandbox_ffa_rxtx_unmap(emul, args, res);
 | 
			
		||||
		break;
 | 
			
		||||
	case FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ):
 | 
			
		||||
		ret = sandbox_ffa_msg_send_direct_req(emul, args, res);
 | 
			
		||||
		break;
 | 
			
		||||
	case FFA_SMC_32(FFA_ID_GET):
 | 
			
		||||
		ret = sandbox_ffa_id_get(emul, args, res);
 | 
			
		||||
		break;
 | 
			
		||||
	case FFA_SMC_32(FFA_FEATURES):
 | 
			
		||||
		ret = sandbox_ffa_features(args, res);
 | 
			
		||||
		break;
 | 
			
		||||
	case FFA_SMC_64(FFA_RXTX_MAP):
 | 
			
		||||
		ret = sandbox_ffa_rxtx_map(emul, args, res);
 | 
			
		||||
		break;
 | 
			
		||||
	case FFA_SMC_32(FFA_RX_RELEASE):
 | 
			
		||||
		ret = sandbox_ffa_rx_release(emul, args, res);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		log_err("Undefined FF-A interface (%lx)\n",
 | 
			
		||||
			args->a0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ret != 0)
 | 
			
		||||
		log_err("FF-A ABI internal failure (%d)\n", ret);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * invoke_ffa_fn() - SMC wrapper
 | 
			
		||||
 * @args: FF-A ABI arguments to be copied to Xn registers
 | 
			
		||||
 * @res: FF-A ABI return data to be copied from Xn registers
 | 
			
		||||
 *
 | 
			
		||||
 * Calls the emulated SMC call.
 | 
			
		||||
 */
 | 
			
		||||
void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
 | 
			
		||||
{
 | 
			
		||||
	sandbox_arm_ffa_smccc_smc(&args, res);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ffa_emul_find() - Find the FF-A emulator
 | 
			
		||||
 * @dev:	the sandbox FF-A device (sandbox-arm-ffa)
 | 
			
		||||
 * @emulp:	the FF-A emulator device (sandbox-ffa-emul)
 | 
			
		||||
 *
 | 
			
		||||
 * Search for the FF-A emulator and returns its device pointer.
 | 
			
		||||
 *
 | 
			
		||||
 * Return:
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
int ffa_emul_find(struct udevice *dev, struct udevice **emulp)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = uclass_first_device_err(UCLASS_FFA_EMUL, emulp);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		log_err("Cannot find FF-A emulator\n");
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_info("FF-A emulator ready to use\n");
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UCLASS_DRIVER(ffa_emul) = {
 | 
			
		||||
	.name		= "ffa_emul",
 | 
			
		||||
	.id		= UCLASS_FFA_EMUL,
 | 
			
		||||
	.post_bind = dm_scan_fdt_dev,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct udevice_id sandbox_ffa_emul_ids[] = {
 | 
			
		||||
	{ .compatible = "sandbox,arm-ffa-emul" },
 | 
			
		||||
	{ }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Declaring the sandbox FF-A emulator under UCLASS_FFA_EMUL */
 | 
			
		||||
U_BOOT_DRIVER(sandbox_ffa_emul) = {
 | 
			
		||||
	.name		= "sandbox_ffa_emul",
 | 
			
		||||
	.id		= UCLASS_FFA_EMUL,
 | 
			
		||||
	.of_match	= sandbox_ffa_emul_ids,
 | 
			
		||||
	.priv_auto	= sizeof(struct sandbox_ffa_emul),
 | 
			
		||||
};
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0+ */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 | 
			
		||||
 *
 | 
			
		||||
 * Authors:
 | 
			
		||||
 *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SANDBOX_ARM_FFA_PRV_H
 | 
			
		||||
#define __SANDBOX_ARM_FFA_PRV_H
 | 
			
		||||
 | 
			
		||||
/* Future sandbox support private declarations */
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										110
									
								
								drivers/firmware/arm-ffa/sandbox_ffa.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								drivers/firmware/arm-ffa/sandbox_ffa.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,110 @@
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0+
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 | 
			
		||||
 *
 | 
			
		||||
 * Authors:
 | 
			
		||||
 *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
 | 
			
		||||
 */
 | 
			
		||||
#include <common.h>
 | 
			
		||||
#include <arm_ffa.h>
 | 
			
		||||
#include <dm.h>
 | 
			
		||||
#include <log.h>
 | 
			
		||||
#include <asm/global_data.h>
 | 
			
		||||
#include <asm/sandbox_arm_ffa_priv.h>
 | 
			
		||||
#include <dm/device-internal.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
 | 
			
		||||
DECLARE_GLOBAL_DATA_PTR;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_discover() - perform sandbox FF-A discovery
 | 
			
		||||
 * @dev: The sandbox FF-A bus device
 | 
			
		||||
 * Try to discover the FF-A framework. Discovery is performed by
 | 
			
		||||
 * querying the FF-A framework version from secure world using the FFA_VERSION ABI.
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success. Otherwise, failure
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_discover(struct udevice *dev)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct udevice *emul;
 | 
			
		||||
 | 
			
		||||
	log_info("Emulated FF-A framework discovery\n");
 | 
			
		||||
 | 
			
		||||
	ret = ffa_emul_find(dev, &emul);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		log_err("Cannot find FF-A emulator\n");
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = ffa_get_version_hdlr(dev);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_probe() - The sandbox FF-A driver probe function
 | 
			
		||||
 * @dev:	the sandbox-arm-ffa device
 | 
			
		||||
 * Save the emulator device in uc_priv.
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success.
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_probe(struct udevice *dev)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	struct ffa_priv *uc_priv = dev_get_uclass_priv(dev);
 | 
			
		||||
 | 
			
		||||
	ret = uclass_first_device_err(UCLASS_FFA_EMUL, &uc_priv->emul);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		log_err("Cannot find FF-A emulator\n");
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * sandbox_ffa_bind() - The sandbox FF-A driver bind function
 | 
			
		||||
 * @dev:	the sandbox-arm-ffa device
 | 
			
		||||
 * Try to discover the emulated FF-A bus.
 | 
			
		||||
 * Return:
 | 
			
		||||
 *
 | 
			
		||||
 * 0 on success.
 | 
			
		||||
 */
 | 
			
		||||
static int sandbox_ffa_bind(struct udevice *dev)
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = sandbox_ffa_discover(dev);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Sandbox Arm FF-A emulator operations */
 | 
			
		||||
 | 
			
		||||
static const struct ffa_bus_ops sandbox_ffa_ops = {
 | 
			
		||||
	.partition_info_get = ffa_get_partitions_info_hdlr,
 | 
			
		||||
	.sync_send_receive = ffa_msg_send_direct_req_hdlr,
 | 
			
		||||
	.rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct udevice_id sandbox_ffa_id[] = {
 | 
			
		||||
	{ "sandbox,arm-ffa", 0 },
 | 
			
		||||
	{ },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Declaring the sandbox FF-A driver under UCLASS_FFA */
 | 
			
		||||
U_BOOT_DRIVER(sandbox_arm_ffa) = {
 | 
			
		||||
	.name		= "sandbox_arm_ffa",
 | 
			
		||||
	.of_match = sandbox_ffa_id,
 | 
			
		||||
	.id		= UCLASS_FFA,
 | 
			
		||||
	.bind		= sandbox_ffa_bind,
 | 
			
		||||
	.probe		= sandbox_ffa_probe,
 | 
			
		||||
	.ops		= &sandbox_ffa_ops,
 | 
			
		||||
};
 | 
			
		||||
@ -63,6 +63,7 @@ enum uclass_id {
 | 
			
		||||
	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 | 
			
		||||
	UCLASS_EXTCON,		/* External Connector Class */
 | 
			
		||||
	UCLASS_FFA,		/* Arm Firmware Framework for Armv8-A */
 | 
			
		||||
	UCLASS_FFA_EMUL,		/* sandbox FF-A device emulator */
 | 
			
		||||
	UCLASS_FIRMWARE,	/* Firmware */
 | 
			
		||||
	UCLASS_FPGA,		/* FPGA device */
 | 
			
		||||
	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user