arm_ffa: introduce Arm FF-A support

Add Arm FF-A support implementing Arm Firmware Framework for Armv8-A v1.0

The Firmware Framework for Arm A-profile processors (FF-A v1.0) [1]
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.

This driver uses 64-bit registers as per SMCCCv1.2 spec and comes
on top of the SMCCC layer. The driver provides the FF-A ABIs needed for
querying the FF-A framework from the secure world.

The driver uses SMC32 calling convention which means using the first
32-bit data of the Xn registers.

All supported ABIs come with their 32-bit version except FFA_RXTX_MAP
which has 64-bit version supported.

Both 32-bit and 64-bit direct messaging are supported which allows both
32-bit and 64-bit clients to use the FF-A bus.

FF-A is a discoverable bus and similar to architecture features.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.

Clients are able to probe then use the FF-A bus by calling the DM class
searching APIs (e.g: uclass_first_device).

The Secure World is considered as one entity to communicate with
using the FF-A bus. FF-A communication is handled by one device and
one instance (the bus). This FF-A driver takes care of all the
interactions between Normal world and Secure World.

The driver exports its operations to be used by upper layers.

Exported operations:

- ffa_partition_info_get
- ffa_sync_send_receive
- ffa_rxtx_unmap

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 please refer to the driver documentation [2].

[1]: https://developer.arm.com/documentation/den0077/latest/
[2]: doc/arch/arm64.ffa.rst

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Jens Wiklander <jens.wiklander@linaro.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
Abdellatif El Khlifi 2023-08-04 14:33:40 +01:00 committed by Tom Rini
parent b83dc8df64
commit 39d383bdac
13 changed files with 1939 additions and 0 deletions

View File

@ -266,6 +266,14 @@ F: drivers/net/cortina_ni.h
F: drivers/net/phy/ca_phy.c
F: configs/cortina_presidio-asic-pnand_defconfig
ARM FF-A
M: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
S: Maintained
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>
M: Fabio Estevam <festevam@gmail.com>

236
doc/arch/arm64.ffa.rst Normal file
View File

@ -0,0 +1,236 @@
.. SPDX-License-Identifier: GPL-2.0+
Arm FF-A Support
================
Summary
-------
FF-A stands for Firmware Framework for Arm A-profile processors.
FF-A specifies interfaces that enable a pair of software execution environments aka partitions to
communicate with each other. A partition could be a VM in the Normal or Secure world, an
application in S-EL0, or a Trusted OS in S-EL1.
The U-Boot FF-A support (the bus) implements the interfaces to communicate
with partitions in the Secure world aka Secure partitions (SPs).
The FF-A support specifically focuses on communicating with SPs that
isolate portions of EFI runtime services that must run in a protected
environment which is inaccessible by the Host OS or Hypervisor.
Examples of such services are set/get variables.
The FF-A support uses the SMC ABIs defined by the FF-A specification to:
- Discover the presence of SPs of interest
- Access an SP's service through communication protocols
e.g. EFI MM communication protocol
At this stage of development only EFI boot-time services are supported.
Runtime support will be added in future developments.
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.
FF-A and SMC specifications
-------------------------------------------
The current implementation of the U-Boot FF-A support relies on
`FF-A v1.0 specification`_ and uses SMC32 calling convention which
means using the first 32-bit data of the Xn registers.
At this stage we only need the FF-A v1.0 features.
The FF-A support has been tested with OP-TEE which supports SMC32 calling
convention.
Hypervisors are supported if they are configured to trap SMC calls.
The FF-A support uses 64-bit registers as per `SMC Calling Convention v1.2 specification`_.
Supported hardware
--------------------------------
Aarch64 plaforms
Configuration
----------------------
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.
FF-A ABIs under the hood
---------------------------------------
Invoking an FF-A ABI involves providing to the secure world/hypervisor the
expected arguments from the ABI.
On an Arm 64-bit platform, the ABI arguments are stored in x0 to x7 registers.
Then, an SMC instruction is executed.
At the secure side level or hypervisor the ABI is handled at a higher exception
level and the arguments are read and processed.
The response is put back through x0 to x7 registers and control is given back
to the U-Boot Arm FF-A driver (non-secure world).
The driver reads the response and processes it accordingly.
This methodology applies to all the FF-A ABIs.
FF-A bus discovery on Arm 64-bit platforms
---------------------------------------------
When CONFIG_ARM_FFA_TRANSPORT is enabled, the FF-A bus is considered as
an architecture feature and discovered using ARM_SMCCC_FEATURES mechanism.
This discovery mechanism is performed by the PSCI driver.
The PSCI driver comes with a PSCI device tree node which is the root node for all
architecture features including FF-A bus.
::
=> dm tree
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.
In case of FF-A, the callback is arm_ffa_is_supported() which tries to discover the
FF-A framework by querying the FF-A framework version from secure world using
FFA_VERSION ABI. When discovery is successful, the ARM_SMCCC_FEATURES
mechanism creates a U-Boot device for the FF-A bus and binds the Arm FF-A driver
with the device using device_bind_driver().
At this stage the FF-A bus is registered with the DM and can be interacted with using
the DM APIs.
Clients are able to probe then use the FF-A bus by calling uclass_first_device().
When calling uclass_first_device(), the FF-A driver is probed and ends up calling
ffa_do_probe() provided by the Uclass which does the following:
- saving the FF-A framework version in uc_priv
- querying from secure world the u-boot endpoint ID
- querying from secure world the supported features of FFA_RXTX_MAP
- mapping the RX/TX buffers
- querying from secure world all the partitions information
When one of the above actions fails, probing fails and the driver stays not active
and can be probed again if needed.
Requirements for clients
-------------------------------------
When using the FF-A bus with EFI, clients must query the SPs they are looking for
during EFI boot-time mode using the service UUID.
The RX/TX buffers are only available at EFI boot-time. Querying partitions is
done at boot time and data is cached for future use.
RX/TX buffers should be unmapped before EFI runtime mode starts.
The driver provides a bus operation for that called ffa_rxtx_unmap().
The user should call ffa_rxtx_unmap() to unmap the RX/TX buffers when required
(e.g: at efi_exit_boot_services()).
The Linux kernel allocates its own RX/TX buffers. To be able to register these kernel buffers
with secure world, the U-Boot's RX/TX buffers should be unmapped before EFI runtime starts.
When invoking FF-A direct messaging, clients should specify which ABI protocol
they want to use (32-bit vs 64-bit). Selecting the protocol means using
the 32-bit or 64-bit version of FFA_MSG_SEND_DIRECT_{REQ, RESP}.
The calling convention between U-Boot and the secure world stays the same: SMC32.
Requirements for user drivers
-------------------------------------
Users who want to implement their custom FF-A device driver while reusing the FF-A Uclass can do so
by implementing their own invoke_ffa_fn() in the user driver.
The bus driver layer
------------------------------
FF-A support comes on top of the SMCCC layer and is implemented by the FF-A Uclass drivers/firmware/arm-ffa/arm-ffa-uclass.c
The following features are provided:
- Support for the 32-bit version of the following ABIs:
- FFA_VERSION
- FFA_ID_GET
- FFA_FEATURES
- FFA_PARTITION_INFO_GET
- FFA_RXTX_UNMAP
- FFA_RX_RELEASE
- FFA_RUN
- FFA_ERROR
- FFA_SUCCESS
- FFA_INTERRUPT
- FFA_MSG_SEND_DIRECT_REQ
- FFA_MSG_SEND_DIRECT_RESP
- Support for the 64-bit version of the following ABIs:
- FFA_RXTX_MAP
- FFA_MSG_SEND_DIRECT_REQ
- FFA_MSG_SEND_DIRECT_RESP
- Processing the received data from the secure world/hypervisor and caching it
- Hiding from upper layers the FF-A protocol and registers details. Upper
layers focus on exchanged data, FF-A support takes care of how to transport
that to the secure world/hypervisor using FF-A
- FF-A support provides driver operations to be used by upper layers:
- ffa_partition_info_get
- ffa_sync_send_receive
- ffa_rxtx_unmap
- FF-A bus discovery makes sure FF-A framework is responsive and compatible
with the driver
- FF-A bus can be compiled and used without EFI
Example of boot logs with FF-A enabled
--------------------------------------
For example, when using FF-A with Corstone-1000 the logs are as follows:
::
U-Boot 2023.01 (May 10 2023 - 11:08:07 +0000) corstone1000 aarch64
DRAM: 2 GiB
Arm FF-A framework discovery
FF-A driver 1.0
FF-A framework 1.0
FF-A versions are compatible
...
FF-A driver 1.0
FF-A framework 1.0
FF-A versions are compatible
EFI: MM partition ID 0x8003
...
EFI stub: Booting Linux Kernel...
...
Linux version 6.1.9-yocto-standard (oe-user@oe-host) (aarch64-poky-linux-musl-gcc (GCC) 12.2.0, GNU ld (GNU Binutils) 2.40.202301193
Machine model: ARM Corstone1000 FPGA MPS3 board
Contributors
------------
* Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
.. _`FF-A v1.0 specification`: https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e
.. _`SMC Calling Convention v1.2 specification`: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6

View File

@ -8,6 +8,7 @@ Architecture-specific doc
arc
arm64
arm64.ffa
m68k
mips
nios2

View File

@ -115,6 +115,7 @@ obj-y += iommu/
obj-y += smem/
obj-y += thermal/
obj-$(CONFIG_TEE) += tee/
obj-$(CONFIG_ARM_FFA_TRANSPORT) += firmware/arm-ffa/
obj-y += axi/
obj-y += ufs/
obj-$(CONFIG_W1) += w1/

View File

@ -45,4 +45,5 @@ config ARM_SMCCC_FEATURES
the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
services if any and reported as supported by the SMCCC firmware.
source "drivers/firmware/arm-ffa/Kconfig"
source "drivers/firmware/scmi/Kconfig"

View File

@ -0,0 +1,36 @@
# SPDX-License-Identifier: GPL-2.0
config ARM_FFA_TRANSPORT
bool "Enable Arm Firmware Framework for Armv8-A driver"
depends on DM && ARM64
select ARM_SMCCC
select ARM_SMCCC_FEATURES
select LIB_UUID
select DEVRES
help
The Firmware Framework for Arm A-profile processors (FF-A)
describes interfaces (ABIs) that standardize communication
between the Secure World and Normal World leveraging TrustZone
technology.
The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32
calling convention.
FF-A specification:
https://developer.arm.com/documentation/den0077/a/?lang=en
In U-Boot FF-A design, FF-A is considered as a discoverable bus.
FF-A bus is discovered using ARM_SMCCC_FEATURES mechanism performed
by the PSCI driver.
The Secure World is considered as one entity to communicate with
using the FF-A bus.
FF-A communication is handled by one device and one instance (the bus).
The FF-A support on U-Boot takes care of all the interactions between Normal
world and Secure World.
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

View File

@ -0,0 +1,8 @@
# 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>
obj-y += arm-ffa-uclass.o arm-ffa.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,104 @@
// 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 <arm_ffa_priv.h>
#include <dm.h>
#include <log.h>
#include <asm/global_data.h>
#include <dm/device-internal.h>
#include <linux/errno.h>
DECLARE_GLOBAL_DATA_PTR;
/**
* 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 low level SMC assembly function
*/
void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)
{
arm_smccc_1_2_smc(&args, res);
}
/**
* arm_ffa_discover() - perform FF-A discovery
* @dev: The Arm FF-A bus device (arm_ffa)
* 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:
*
* true on success. Otherwise, false.
*/
static bool arm_ffa_discover(struct udevice *dev)
{
int ret;
log_info("Arm FF-A framework discovery\n");
ret = ffa_get_version_hdlr(dev);
if (ret)
return false;
return true;
}
/**
* arm_ffa_is_supported() - FF-A bus discovery callback
* @invoke_fn: legacy SMC invoke function (not used)
*
* Perform FF-A discovery by calling arm_ffa_discover().
* Discovery is performed by querying the FF-A framework version from
* secure world using the FFA_VERSION ABI.
*
* The FF-A driver is registered as an SMCCC feature driver. So, features discovery
* callbacks are called by the PSCI driver (PSCI device is the SMCCC features
* root device).
*
* The FF-A driver supports the SMCCCv1.2 extended input/output registers.
* So, the legacy SMC invocation is not used.
*
* Return:
*
* 0 on success. Otherwise, failure
*/
static bool arm_ffa_is_supported(void (*invoke_fn)(ulong a0, ulong a1,
ulong a2, ulong a3,
ulong a4, ulong a5,
ulong a6, ulong a7,
struct arm_smccc_res *res))
{
return arm_ffa_discover(NULL);
}
/* Arm FF-A driver operations */
static const struct ffa_bus_ops 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,
};
/* Registering the FF-A driver as an SMCCC feature driver */
ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = {
.driver_name = FFA_DRV_NAME,
.is_supported = arm_ffa_is_supported,
};
/* Declaring the FF-A driver under UCLASS_FFA */
U_BOOT_DRIVER(arm_ffa) = {
.name = FFA_DRV_NAME,
.id = UCLASS_FFA,
.flags = DM_REMOVE_OS_PREPARE,
.ops = &ffa_ops,
};

View File

@ -0,0 +1,14 @@
/* 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

213
include/arm_ffa.h Normal file
View File

@ -0,0 +1,213 @@
/* 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 __ARM_FFA_H
#define __ARM_FFA_H
#include <linux/printk.h>
/*
* This header is public. It can be used by clients to access
* data structures and definitions they need
*/
/*
* struct ffa_partition_info - Partition information descriptor
* @id: Partition ID
* @exec_ctxt: Execution context count
* @properties: Partition properties
*
* Data structure containing information about partitions instantiated in the system
* This structure is filled with the data queried by FFA_PARTITION_INFO_GET
*/
struct ffa_partition_info {
u16 id;
u16 exec_ctxt;
/* partition supports receipt of direct requests */
#define FFA_PARTITION_DIRECT_RECV BIT(0)
/* partition can send direct requests. */
#define FFA_PARTITION_DIRECT_SEND BIT(1)
/* partition can send and receive indirect messages. */
#define FFA_PARTITION_INDIRECT_MSG BIT(2)
u32 properties;
};
/*
* struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
* @a1-4: 32-bit words access to the UUID data
*
*/
struct ffa_partition_uuid {
u32 a1; /* w1 */
u32 a2; /* w2 */
u32 a3; /* w3 */
u32 a4; /* w4 */
};
/**
* struct ffa_partition_desc - the secure partition descriptor
* @info: partition information
* @sp_uuid: the secure partition UUID
*
* Each partition has its descriptor containing the partitions information and the UUID
*/
struct ffa_partition_desc {
struct ffa_partition_info info;
struct ffa_partition_uuid sp_uuid;
};
/*
* struct ffa_send_direct_data - Data structure hosting the data
* used by FFA_MSG_SEND_DIRECT_{REQ,RESP}
* @data0-4: Data read/written from/to x3-x7 registers
*
* Data structure containing the data to be sent by FFA_MSG_SEND_DIRECT_REQ
* or read from FFA_MSG_SEND_DIRECT_RESP
*/
/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
struct ffa_send_direct_data {
ulong data0; /* w3/x3 */
ulong data1; /* w4/x4 */
ulong data2; /* w5/x5 */
ulong data3; /* w6/x6 */
ulong data4; /* w7/x7 */
};
struct udevice;
/**
* struct ffa_bus_ops - Operations for FF-A
* @partition_info_get: callback for the FFA_PARTITION_INFO_GET
* @sync_send_receive: callback for the FFA_MSG_SEND_DIRECT_REQ
* @rxtx_unmap: callback for the FFA_RXTX_UNMAP
*
* The data structure providing all the operations supported by the driver.
* This structure is EFI runtime resident.
*/
struct ffa_bus_ops {
int (*partition_info_get)(struct udevice *dev, const char *uuid_str,
u32 *sp_count, struct ffa_partition_desc **sp_descs);
int (*sync_send_receive)(struct udevice *dev, u16 dst_part_id,
struct ffa_send_direct_data *msg,
bool is_smc64);
int (*rxtx_unmap)(struct udevice *dev);
};
#define ffa_get_ops(dev) ((struct ffa_bus_ops *)(dev)->driver->ops)
/**
* ffa_rxtx_unmap() - FFA_RXTX_UNMAP driver operation
* Please see ffa_unmap_rxtx_buffers_hdlr() description for more details.
*/
int ffa_rxtx_unmap(struct udevice *dev);
/**
* ffa_unmap_rxtx_buffers_hdlr() - FFA_RXTX_UNMAP handler function
* @dev: The arm_ffa bus device
*
* This function implements FFA_RXTX_UNMAP FF-A function
* to unmap the RX/TX buffers
*
* Return:
*
* 0 on success. Otherwise, failure
*/
int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev);
/**
* ffa_sync_send_receive() - FFA_MSG_SEND_DIRECT_{REQ,RESP} driver operation
* Please see ffa_msg_send_direct_req_hdlr() description for more details.
*/
int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,
struct ffa_send_direct_data *msg, bool is_smc64);
/**
* ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
* @dev: The arm_ffa bus device
* @dst_part_id: destination partition ID
* @msg: pointer to the message data preallocated by the client (in/out)
* @is_smc64: select 64-bit or 32-bit FF-A ABI
*
* This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}
* FF-A functions.
*
* FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.
* The response from the secure partition is handled by reading the
* FFA_MSG_SEND_DIRECT_RESP arguments.
*
* The maximum size of the data that can be exchanged is 40 bytes which is
* sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0
* in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}
*
* Return:
*
* 0 on success. Otherwise, failure
*/
int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,
struct ffa_send_direct_data *msg, bool is_smc64);
/**
* ffa_partition_info_get() - FFA_PARTITION_INFO_GET driver operation
* Please see ffa_get_partitions_info_hdlr() description for more details.
*/
int ffa_partition_info_get(struct udevice *dev, const char *uuid_str,
u32 *sp_count, struct ffa_partition_desc **sp_descs);
/**
* ffa_get_partitions_info_hdlr() - FFA_PARTITION_INFO_GET handler function
* @uuid_str: pointer to the UUID string
* @sp_count: address of the variable containing the number of partitions matching the UUID
* The variable is set by the driver
* @sp_descs: address of the descriptors of the partitions matching the UUID
* The address is set by the driver
*
* Return the number of partitions and their descriptors matching the UUID
*
* Query the secure partition data from uc_priv.
* If not found, invoke FFA_PARTITION_INFO_GET
* FF-A function to query the partition information from secure world.
*
* A client of the FF-A driver should know the UUID of the service it wants to
* access. It should use the UUID to request the FF-A driver to provide the
* partition(s) information of the service. The FF-A driver uses
* PARTITION_INFO_GET to obtain this information. This is implemented through
* ffa_get_partitions_info_hdlr() function.
* A new FFA_PARTITION_INFO_GET call is issued (first one performed through
* ffa_cache_partitions_info) allowing to retrieve the partition(s) information.
* They are not saved (already done). We only update the UUID in the cached area.
* This assumes that partitions data does not change in the secure world.
* Otherwise u-boot will have an outdated partition data. The benefit of caching
* the information in the FF-A driver is to accommodate discovery after
* ExitBootServices().
*
* Return:
*
* @sp_count: the number of partitions
* @sp_descs: address of the partitions descriptors
*
* On success 0 is returned. Otherwise, failure
*/
int ffa_get_partitions_info_hdlr(struct udevice *dev, const char *uuid_str,
u32 *sp_count, struct ffa_partition_desc **sp_descs);
struct ffa_priv;
/**
* ffa_set_smc_conduit() - Set the SMC conduit
* @dev: The FF-A bus device
*
* Selects the SMC conduit by setting the FF-A ABI invoke function.
*
* Return:
*
* 0 on success. Otherwise, failure
*/
int ffa_set_smc_conduit(struct udevice *dev);
#endif

246
include/arm_ffa_priv.h Normal file
View File

@ -0,0 +1,246 @@
/* 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 __ARM_FFA_PRV_H
#define __ARM_FFA_PRV_H
#include <mapmem.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
/* This header is exclusively used by the FF-A Uclass and FF-A driver(s) */
/* Arm FF-A driver name */
#define FFA_DRV_NAME "arm_ffa"
/* The FF-A SMC function definitions */
#if CONFIG_IS_ENABLED(SANDBOX)
/* Providing Arm SMCCC declarations to sandbox */
/**
* struct sandbox_smccc_1_2_regs - emulated SMC call arguments or results
* @a0-a17 argument values from registers 0 to 17
*/
struct sandbox_smccc_1_2_regs {
ulong a0;
ulong a1;
ulong a2;
ulong a3;
ulong a4;
ulong a5;
ulong a6;
ulong a7;
ulong a8;
ulong a9;
ulong a10;
ulong a11;
ulong a12;
ulong a13;
ulong a14;
ulong a15;
ulong a16;
ulong a17;
};
typedef struct sandbox_smccc_1_2_regs ffa_value_t;
#define ARM_SMCCC_FAST_CALL 1UL
#define ARM_SMCCC_OWNER_STANDARD 4
#define ARM_SMCCC_SMC_32 0
#define ARM_SMCCC_SMC_64 1
#define ARM_SMCCC_TYPE_SHIFT 31
#define ARM_SMCCC_CALL_CONV_SHIFT 30
#define ARM_SMCCC_OWNER_MASK 0x3f
#define ARM_SMCCC_OWNER_SHIFT 24
#define ARM_SMCCC_FUNC_MASK 0xffff
#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \
(((type) << ARM_SMCCC_TYPE_SHIFT) | \
((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \
(((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \
((func_num) & ARM_SMCCC_FUNC_MASK))
#else
/* CONFIG_ARM64 */
#include <linux/arm-smccc.h>
typedef struct arm_smccc_1_2_regs ffa_value_t;
#endif
/* Defining the function pointer type for the function executing the FF-A ABIs */
typedef void (*invoke_ffa_fn_t)(ffa_value_t args, ffa_value_t *res);
/* FF-A driver version definitions */
#define MAJOR_VERSION_MASK GENMASK(30, 16)
#define MINOR_VERSION_MASK GENMASK(15, 0)
#define GET_FFA_MAJOR_VERSION(x) \
((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
#define GET_FFA_MINOR_VERSION(x) \
((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
#define PACK_VERSION_INFO(major, minor) \
(FIELD_PREP(MAJOR_VERSION_MASK, (major)) | \
FIELD_PREP(MINOR_VERSION_MASK, (minor)))
#define FFA_MAJOR_VERSION (1)
#define FFA_MINOR_VERSION (0)
#define FFA_VERSION_1_0 \
PACK_VERSION_INFO(FFA_MAJOR_VERSION, FFA_MINOR_VERSION)
/* Endpoint ID mask (u-boot endpoint ID) */
#define GET_SELF_ENDPOINT_ID_MASK GENMASK(15, 0)
#define GET_SELF_ENDPOINT_ID(x) \
((u16)(FIELD_GET(GET_SELF_ENDPOINT_ID_MASK, (x))))
#define PREP_SELF_ENDPOINT_ID_MASK GENMASK(31, 16)
#define PREP_SELF_ENDPOINT_ID(x) \
(FIELD_PREP(PREP_SELF_ENDPOINT_ID_MASK, (x)))
/* Partition endpoint ID mask (partition with which u-boot communicates with) */
#define PREP_PART_ENDPOINT_ID_MASK GENMASK(15, 0)
#define PREP_PART_ENDPOINT_ID(x) \
(FIELD_PREP(PREP_PART_ENDPOINT_ID_MASK, (x)))
/* Definitions of the Arm FF-A interfaces supported by the Arm FF-A driver */
#define FFA_SMC(calling_convention, func_num) \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention), \
ARM_SMCCC_OWNER_STANDARD, (func_num))
#define FFA_SMC_32(func_num) FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
#define FFA_SMC_64(func_num) FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
enum ffa_abis {
FFA_ERROR = 0x60,
FFA_SUCCESS = 0x61,
FFA_INTERRUPT = 0x62,
FFA_VERSION = 0x63,
FFA_FEATURES = 0x64,
FFA_RX_RELEASE = 0x65,
FFA_RXTX_MAP = 0x66,
FFA_RXTX_UNMAP = 0x67,
FFA_PARTITION_INFO_GET = 0x68,
FFA_ID_GET = 0x69,
FFA_RUN = 0x6d,
FFA_MSG_SEND_DIRECT_REQ = 0x6f,
FFA_MSG_SEND_DIRECT_RESP = 0x70,
/* To be updated when adding new FFA IDs */
FFA_FIRST_ID = FFA_ERROR, /* Lowest number ID */
FFA_LAST_ID = FFA_MSG_SEND_DIRECT_RESP, /* Highest number ID */
};
enum ffa_abi_errcode {
NOT_SUPPORTED = 1,
INVALID_PARAMETERS,
NO_MEMORY,
BUSY,
INTERRUPTED,
DENIED,
RETRY,
ABORTED,
MAX_NUMBER_FFA_ERR
};
extern int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR];
/* Container structure and helper macros to map between an FF-A error and relevant error log */
struct ffa_abi_errmap {
char *err_str[MAX_NUMBER_FFA_ERR];
};
#define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
#define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
/**
* enum ffa_rxtx_buf_sizes - minimum sizes supported
* for the RX/TX buffers
*/
enum ffa_rxtx_buf_sizes {
RXTX_4K,
RXTX_64K,
RXTX_16K
};
/**
* struct ffa_rxtxpair - Hosts the RX/TX buffers virtual addresses
* @rxbuf: virtual address of the RX buffer
* @txbuf: virtual address of the TX buffer
* @rxtx_min_pages: RX/TX buffers minimum size in pages
*
* Hosts the virtual addresses of the mapped RX/TX buffers
* These addresses are used by the FF-A functions that use the RX/TX buffers
*/
struct ffa_rxtxpair {
void *rxbuf; /* Virtual address returned by memalign */
void *txbuf; /* Virtual address returned by memalign */
size_t rxtx_min_pages; /* Minimum number of pages in each of the RX/TX buffers */
};
struct ffa_partition_desc;
/**
* struct ffa_partitions - descriptors for all secure partitions
* @count: The number of partitions descriptors
* @descs The partitions descriptors table
*
* Contains the partitions descriptors table
*/
struct ffa_partitions {
u32 count;
struct ffa_partition_desc *descs; /* Virtual address */
};
/**
* struct ffa_priv - the driver private data structure
*
* @fwk_version: FF-A framework version
* @emul: FF-A sandbox emulator
* @id: u-boot endpoint ID
* @partitions: The partitions descriptors structure
* @pair: The RX/TX buffers pair
*
* The device private data structure containing all the
* data read from secure world.
*/
struct ffa_priv {
u32 fwk_version;
struct udevice *emul;
u16 id;
struct ffa_partitions partitions;
struct ffa_rxtxpair pair;
};
/**
* ffa_get_version_hdlr() - FFA_VERSION handler function
* @dev: The FF-A bus device
*
* Implement FFA_VERSION FF-A function
* to get from the secure world the FF-A framework version
* FFA_VERSION is used to discover the FF-A framework.
*
* Return:
*
* 0 on success. Otherwise, failure
*/
int ffa_get_version_hdlr(struct udevice *dev);
/**
* 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 low level SMC implementation.
* This function should be implemented by the user driver.
*/
void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res);
#endif

View File

@ -4,6 +4,11 @@
*
* (C) Copyright 2012
* Pavel Herrmann <morpheus.ibis@gmail.com>
*
* Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
*
* Authors:
* Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
*/
#ifndef _DM_UCLASS_ID_H
@ -57,6 +62,7 @@ enum uclass_id {
UCLASS_ETH, /* Ethernet device */
UCLASS_ETH_PHY, /* Ethernet PHY device */
UCLASS_EXTCON, /* External Connector Class */
UCLASS_FFA, /* Arm Firmware Framework for Armv8-A */
UCLASS_FIRMWARE, /* Firmware */
UCLASS_FPGA, /* FPGA device */
UCLASS_FUZZING_ENGINE, /* Fuzzing engine */