From c13d4bd7d4d863445689a1e6a2ee1e2ba2e4cfce Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Tue, 2 Jun 2020 17:58:28 +0200 Subject: core: add optee_ffa.h defining the OP-TEE ABI for FF-A Adds optee_ffa.h which defines the OP-TEE ABI when Arm Platform Security Architecture Firmware Framework for Arm V8-A [1] is used as transport instead of raw proprietary SMCs. This ABI where OP-TEE specific implementation is used to fill the implementation specific gaps in the specification is called OP-TEE FF-A, or sometimes just FF-A. A new memref type, struct optee_msg_param_fmem, is added to carry information needed to create new shared memory mobjs. Link: [1] https://static.docs.arm.com/den0077/a/DEN0077A_PSA_Firmware_Framework_Arm_v8-A_1.0_EAC.pdf Acked-by: Etienne Carriere Signed-off-by: Jens Wiklander --- core/arch/arm/include/optee_ffa.h | 201 ++++++++++++++++++++++++++++++++++++++ core/include/optee_msg.h | 49 +++++++--- 2 files changed, 237 insertions(+), 13 deletions(-) create mode 100644 core/arch/arm/include/optee_ffa.h diff --git a/core/arch/arm/include/optee_ffa.h b/core/arch/arm/include/optee_ffa.h new file mode 100644 index 00000000..8498fbab --- /dev/null +++ b/core/arch/arm/include/optee_ffa.h @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ + +/* + * This file is exported by OP-TEE and is kept in sync between secure world + * and normal world drivers. We're using ARM FF-A 1.0 EAC specification. + */ + +#ifndef __OPTEE_FFA_H +#define __OPTEE_FFA_H + +#include + +/* + * Normal world sends requests with FFA_MSG_SEND_DIRECT_REQ and + * responses are returned with FFA_MSG_SEND_DIRECT_RESP for normal + * messages. + * + * All requests with FFA_MSG_SEND_DIRECT_REQ and FFA_MSG_SEND_DIRECT_RESP + * are using the AArch32 SMC calling convention with register usage as + * defined in FF-A specification: + * w0: Function ID (0x8400006F or 0x84000070) + * w1: Source/Destination IDs + * w2: Reserved (MBZ) + * w3-w7: Implementation defined, free to be used below + */ + +#define OPTEE_FFA_VERSION_MAJOR UINT32_C(0) +#define OPTEE_FFA_VERSION_MINOR UINT32_C(9) + +#define OPTEE_FFA_BLOCKING_CALL(id) UINT32_C(id) +#define OPTEE_FFA_YIELDING_CALL_BIT 31 +#define OPTEE_FFA_YIELDING_CALL(id) (UINT32_C(id) | \ + BIT32(OPTEE_FFA_YIELDING_CALL_BIT)) + +/* + * Returns the API version implemented, currently follows the FF-A version. + * Call register usage: + * w3: Service ID, OPTEE_FFA_GET_API_VERSION + * w4-w7: Not used (MBZ) + * + * Return register usage: + * w3: OPTEE_FFA_VERSION_MAJOR + * w4: OPTEE_FFA_VERSION_MINOR + * w5-w7: Not used (MBZ) + */ +#define OPTEE_FFA_GET_API_VERSION OPTEE_FFA_BLOCKING_CALL(0) + +/* + * Returns the revision of OP-TEE. + * + * Used by non-secure world to figure out which version of the Trusted OS + * is installed. Note that the returned revision is the revision of the + * Trusted OS, not of the API. + * + * Call register usage: + * w3: Service ID, OPTEE_FFA_GET_OS_VERSION + * w4-w7: Unused (MBZ) + * + * Return register usage: + * w3: CFG_OPTEE_REVISION_MAJOR + * w4: CFG_OPTEE_REVISION_MINOR + * w5: TEE_IMPL_GIT_SHA1 (or zero if not supported) + */ +#define OPTEE_FFA_GET_OS_VERSION OPTEE_FFA_BLOCKING_CALL(1) + +/* + * Exchange capabilities between normal world and secure world. + * + * Currently there are no defined capabilities. When features are added new + * capabilities may be added. + * + * Call register usage: + * w3: Service ID, OPTEE_FFA_EXCHANGE_CAPABILITIES + * w4-w7: Note used (MBZ) + * + * Return register usage: + * w3: Error code, 0 on success + * w4: Bit[1:0]: Number of 4kB pages of shared memory to register with + * OPTEE_FFA_REGISTER_RPC_SHM to support RPC + * Bit[31:2]: Reserved (MBZ) + * w5-w7: Note used (MBZ) + */ +#define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2) + +/* + * Call with struct optee_msg_arg as argument in the supplied shared memory + * with a zero internal offset and normal cached memory attributes. + * Register usage: + * w3: Service ID, OPTEE_FFA_YIELDING_CALL_WITH_ARG + * w4: Lower 32 bits of a 64-bit Shared memory handle + * w5: Upper 32 bits of a 64-bit Shared memory handle + * w6: Offset into shared memory pointing to a struct optee_msg_arg + * w7: Not used (MBZ) + * + * Call to register shared memory. The data is supplied in shared + * memory with a zero internal offset and normal cached memory attributes. + * The data is formatted as described in FF-A 1.0 EAC Table 44 + * "Lend, donate or share memory transaction descriptor". + * Register usage: + * w3: Service ID, OPTEE_FFA_YIELDING_CALL_REGISTER_SHM + * w4: Lower 32 bits of a 64-bit Shared memory handle + * w5: Upper 32 bits of a 64-bit Shared memory handle + * w6-w7: Not used (MBZ) + * + * Call to unregister shared memory. Register usage: + * w3: Service ID, OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM + * w4: Lower 32 bits of a 64-bit Shared memory handle + * w5: Upper 32 bits of a 64-bit Shared memory handle + * w6-w7: Not used (MBZ) + * + * Resume from RPC. Register usage: + * w3: Service ID, OPTEE_FFA_YIELDING_CALL_RESUME + * If returning from OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SHM: + * w4: Lower 32 bits of a 64-bit Shared memory handle + * w5: Upper 32 bits of a 64-bit Shared memory handle + * If the allocation failed both w4 and w5 are 0 + * w6: Offset into shared memory pointing the table. If internal + * offset > 0 then one more 4kB page than requested has been + * allocated. + * else if resuming from another RPC: + * w4-w6: Not used (MBZ) + * w7: Resume info + * + * Normal return (yielding call is completed). Register usage: + * w3: Error code, 0 on success + * w4: OPTEE_FFA_YIELDING_CALL_RETURN_DONE + * w5-w7: Not used (MBZ) + * + * Alloc SHM return (RPC from secure world). Register usage: + * w3: Error code == 0 + * w4: OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM or + * OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM + * allocate kernel private or supplicant memory respectively. + * w5: Number of 4kB pages of shared memory + * w6: Not used (MBZ) + * w7: Resume info + * + * Free SHM return (RPC from secure world). Register usage: + * w3: Error code == 0 + * w4: OPTEE_FFA_YIELDING_CALL_RETURN_FREE_KERN_SHM or + * OPTEE_FFA_YIELDING_CALL_RETURN_FREE_SUPPL_SHM + * free kernel private or supplicant memory respectively. + * w5: Lower 32 bits of a 64-bit Shared memory handle + * w6: Upper 32 bits of a 64-bit Shared memory handle + * The handle previously allocated with + * OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM or + * OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM. + * w7: Resume info + * + * RPC cmd return (RPC from secure world). Register usage: + * w3: Error code == 0 + * w4: OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD + * w5: Lower 32 bits of a 64-bit Shared memory handle + * w6: Upper 32 bits of a 64-bit Shared memory handle + * The handle contains aed the RPC. + * w7: Resume info + * + * RPC interrupt return (RPC from secure world). Register usage: + * w3: Error code == 0 + * w4: OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT + * w5-w6: Not used (MBZ) + * w7: Resume info + * + * Possible error codes in register w3: + * 0: Success + * FFA_DENIED: w4 isn't one of OPTEE_FFA_YIELDING_CALL_START + * OPTEE_FFA_YIELDING_CALL_REGISTER_SHM, + * OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM or + * OPTEE_FFA_YIELDING_CALL_RESUME + * + * Possible error codes for OPTEE_FFA_YIELDING_CALL_START, + * OPTEE_FFA_YIELDING_CALL_REGISTER_SHM and + * OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM + * FFA_BUSY: Number of OP-TEE OS threads exceeded, + * try again later + * FFA_DENIED: RPC shared memory object not found + * FFA_INVALID_PARAMETER: Bad shared memory handle or offset into the memory + * + * Possible error codes for OPTEE_FFA_YIELDING_CALL_RESUME + * FFA_INVALID_PARAMETER: Bad resume info + */ +#define OPTEE_FFA_YIELDING_CALL_WITH_ARG OPTEE_FFA_YIELDING_CALL(0) +#define OPTEE_FFA_YIELDING_CALL_REGISTER_SHM OPTEE_FFA_YIELDING_CALL(1) +#define OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM OPTEE_FFA_YIELDING_CALL(2) +#define OPTEE_FFA_YIELDING_CALL_RESUME OPTEE_FFA_YIELDING_CALL(3) + +#define OPTEE_FFA_YIELDING_CALL_RETURN_DONE 0 +#define OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM 1 +#define OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM 2 +#define OPTEE_FFA_YIELDING_CALL_RETURN_RESERVED0 3 +#define OPTEE_FFA_YIELDING_CALL_RETURN_FREE_KERN_SHM 4 +#define OPTEE_FFA_YIELDING_CALL_RETURN_FREE_SUPPL_SHM 5 +#define OPTEE_FFA_YIELDING_CALL_RETURN_RESERVED1 6 +#define OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD 7 +#define OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT 8 + +#endif /*__OPTEE_FFA_H*/ + diff --git a/core/include/optee_msg.h b/core/include/optee_msg.h index 72eaeae9..57467c77 100644 --- a/core/include/optee_msg.h +++ b/core/include/optee_msg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* - * Copyright (c) 2015-2017, Linaro Limited + * Copyright (c) 2015-2020, Linaro Limited */ #ifndef _OPTEE_MSG_H #define _OPTEE_MSG_H @@ -25,6 +25,9 @@ #define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT 0x5 #define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT 0x6 #define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT 0x7 +#define OPTEE_MSG_ATTR_TYPE_FMEM_INPUT OPTEE_MSG_ATTR_TYPE_RMEM_INPUT +#define OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT +#define OPTEE_MSG_ATTR_TYPE_FMEM_INOUT OPTEE_MSG_ATTR_TYPE_RMEM_INOUT #define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT 0x9 #define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT 0xa #define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT 0xb @@ -49,8 +52,8 @@ * Every entry in buffer should point to a 4k page beginning (12 least * significant bits must be equal to zero). * - * 12 least significant of optee_msg_param.u.tmem.buf_ptr should hold page - * offset of user buffer. + * 12 least significant bits of optee_msg_param.u.tmem.buf_ptr should hold + * page offset of user buffer. * * So, entries should be placed like members of this structure: * @@ -126,10 +129,26 @@ struct optee_msg_param_rmem { }; /** - * struct optee_msg_param_value - values - * @a: first value - * @b: second value - * @c: third value + * struct optee_msg_param_fmem - FF-A memory reference parameter + * @offs_lower: Lower bits of offset into shared memory reference + * @offs_upper: Upper bits of offset into shared memory reference + * @internal_offs: Internal offset into the first page of shared memory + * reference + * @size: Size of the buffer + * @global_id: Global identifier of the shared memory + */ +struct optee_msg_param_fmem { + uint32_t offs_low; + uint16_t offs_high; + uint16_t internal_offs; + uint64_t size; + uint64_t global_id; +}; + +/** + * struct optee_msg_param_value - opaque value parameter + * + * Value parameters are passed unchecked between normal and secure world. */ struct optee_msg_param_value { uint64_t a; @@ -138,15 +157,18 @@ struct optee_msg_param_value { }; /** - * struct optee_msg_param - parameter - * @attr: attributes - * @memref: a memory reference - * @value: a value + * struct optee_msg_param - parameter used together with struct optee_msg_arg + * @attr: attributes + * @tmem: parameter by temporary memory reference + * @rmem: parameter by registered memory reference + * @fmem: parameter by FF-A registered memory reference + * @value: parameter by opaque value * * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value, - * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates tmem and - * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates rmem. + * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and + * OPTEE_MSG_ATTR_TYPE_RMEM_* or the alias PTEE_MSG_ATTR_TYPE_FMEM_* indicates + * @rmem or @fmem depending on the conduit. * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used. */ struct optee_msg_param { @@ -154,6 +176,7 @@ struct optee_msg_param { union { struct optee_msg_param_tmem tmem; struct optee_msg_param_rmem rmem; + struct optee_msg_param_fmem fmem; struct optee_msg_param_value value; } u; }; -- cgit v1.2.3