From patchwork Fri Mar 10 14:10:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdellatif El Khlifi X-Patchwork-Id: 1755238 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PY7J25Z4Zz1yWl for ; Sat, 11 Mar 2023 01:10:58 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 4552285D8F; Fri, 10 Mar 2023 15:10:42 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id BE37F85AC1; Fri, 10 Mar 2023 15:10:37 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id 1D72085B6E for ; Fri, 10 Mar 2023 15:10:33 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=abdellatif.elkhlifi@arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 1BC1B1515; Fri, 10 Mar 2023 06:11:16 -0800 (PST) Received: from e130802.arm.com (unknown [10.57.64.115]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D6B223F71A; Fri, 10 Mar 2023 06:10:29 -0800 (PST) From: Abdellatif El Khlifi To: sjg@chromium.org Cc: Drew.Reed@arm.com, abdellatif.elkhlifi@arm.com, achin.gupta@arm.com, ilias.apalodimas@linaro.org, jens.wiklander@linaro.org, nd@arm.com, robh@kernel.org, sudeep.holla@arm.com, trini@konsulko.com, u-boot@lists.denx.de, xueliang.zhong@arm.com Subject: [PATCH v9 01/10] arm64: smccc: add support for SMCCCv1.2 x0-x17 registers Date: Fri, 10 Mar 2023 14:10:07 +0000 Message-Id: <20230310141016.137986-2-abdellatif.elkhlifi@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> References: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean add support for x0-x17 registers used by the SMC calls In SMCCC v1.2 [1] arguments are passed in registers x1-x17. Results are returned in x0-x17. This work is inspired from the following kernel commit: arm64: smccc: Add support for SMCCCv1.2 extended input/output registers [1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token= Signed-off-by: Abdellatif El Khlifi Reviewed-by: Jens Wiklander Cc: Tom Rini Cc: Simon Glass Cc: Ilias Apalodimas --- Changelog: =============== v9: * update the copyright string v7: * improve indentation of ARM_SMCCC_1_2_REGS_Xn_OFFS v4: * rename the commit title and improve description new commit title: the current v3: * port x0-x17 registers support from linux kernel as defined by SMCCCv1.2 commit title: arm64: smccc: add Xn registers support used by SMC calls arch/arm/cpu/armv8/smccc-call.S | 57 ++++++++++++++++++++++++++++++++- arch/arm/lib/asm-offsets.c | 16 +++++++++ include/linux/arm-smccc.h | 45 ++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S index dc92b28777..93f66d3366 100644 --- a/arch/arm/cpu/armv8/smccc-call.S +++ b/arch/arm/cpu/armv8/smccc-call.S @@ -1,7 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2015, Linaro Limited - */ + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi +*/ #include #include #include @@ -45,3 +49,54 @@ ENDPROC(__arm_smccc_smc) ENTRY(__arm_smccc_hvc) SMCCC hvc ENDPROC(__arm_smccc_hvc) + +#ifdef CONFIG_ARM64 + + .macro SMCCC_1_2 instr + /* Save `res` and free a GPR that won't be clobbered */ + stp x1, x19, [sp, #-16]! + + /* Ensure `args` won't be clobbered while loading regs in next step */ + mov x19, x0 + + /* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */ + ldp x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS] + ldp x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS] + ldp x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS] + ldp x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS] + ldp x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS] + ldp x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS] + ldp x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS] + ldp x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS] + ldp x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS] + + \instr #0 + + /* Load the `res` from the stack */ + ldr x19, [sp] + + /* Store the registers x0 - x17 into the result structure */ + stp x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS] + stp x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS] + stp x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS] + stp x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS] + stp x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS] + stp x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS] + stp x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS] + stp x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS] + stp x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS] + + /* Restore original x19 */ + ldp xzr, x19, [sp], #16 + ret + .endm + +/* + * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args, + * struct arm_smccc_1_2_regs *res); + */ +ENTRY(arm_smccc_1_2_smc) + SMCCC_1_2 smc +ENDPROC(arm_smccc_1_2_smc) + +#endif diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c index 6de0ce9152..181a8ac4c2 100644 --- a/arch/arm/lib/asm-offsets.c +++ b/arch/arm/lib/asm-offsets.c @@ -9,6 +9,11 @@ * generate asm statements containing #defines, * compile this file to assembler, and then extract the * #defines from the assembly-language output. + * + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi */ #include @@ -90,6 +95,17 @@ int main(void) DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2)); DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id)); DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state)); +#ifdef CONFIG_ARM64 + DEFINE(ARM_SMCCC_1_2_REGS_X0_OFFS, offsetof(struct arm_smccc_1_2_regs, a0)); + DEFINE(ARM_SMCCC_1_2_REGS_X2_OFFS, offsetof(struct arm_smccc_1_2_regs, a2)); + DEFINE(ARM_SMCCC_1_2_REGS_X4_OFFS, offsetof(struct arm_smccc_1_2_regs, a4)); + DEFINE(ARM_SMCCC_1_2_REGS_X6_OFFS, offsetof(struct arm_smccc_1_2_regs, a6)); + DEFINE(ARM_SMCCC_1_2_REGS_X8_OFFS, offsetof(struct arm_smccc_1_2_regs, a8)); + DEFINE(ARM_SMCCC_1_2_REGS_X10_OFFS, offsetof(struct arm_smccc_1_2_regs, a10)); + DEFINE(ARM_SMCCC_1_2_REGS_X12_OFFS, offsetof(struct arm_smccc_1_2_regs, a12)); + DEFINE(ARM_SMCCC_1_2_REGS_X14_OFFS, offsetof(struct arm_smccc_1_2_regs, a14)); + DEFINE(ARM_SMCCC_1_2_REGS_X16_OFFS, offsetof(struct arm_smccc_1_2_regs, a16)); +#endif #endif return 0; diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index e1d09884a1..f44e9e8f93 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -1,6 +1,10 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2015, Linaro Limited + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi */ #ifndef __LINUX_ARM_SMCCC_H #define __LINUX_ARM_SMCCC_H @@ -70,6 +74,47 @@ struct arm_smccc_res { unsigned long a3; }; +#ifdef CONFIG_ARM64 +/** + * struct arm_smccc_1_2_regs - Arguments for or Results from SMC call + * @a0-a17 argument values from registers 0 to 17 + */ +struct arm_smccc_1_2_regs { + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; + unsigned long a4; + unsigned long a5; + unsigned long a6; + unsigned long a7; + unsigned long a8; + unsigned long a9; + unsigned long a10; + unsigned long a11; + unsigned long a12; + unsigned long a13; + unsigned long a14; + unsigned long a15; + unsigned long a16; + unsigned long a17; +}; + +/** + * arm_smccc_1_2_smc() - make SMC calls + * @args: arguments passed via struct arm_smccc_1_2_regs + * @res: result values via struct arm_smccc_1_2_regs + * + * This function is used to make SMC calls following SMC Calling Convention + * v1.2 or above. The content of the supplied param are copied from the + * structure to registers prior to the SMC instruction. The return values + * are updated with the content from registers on return from the SMC + * instruction. + */ +asmlinkage void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args, + struct arm_smccc_1_2_regs *res); +#endif + /** * struct arm_smccc_quirk - Contains quirk information * @id: quirk identification From patchwork Fri Mar 10 14:10:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdellatif El Khlifi X-Patchwork-Id: 1755239 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PY7JH4sMwz1yWl for ; Sat, 11 Mar 2023 01:11:11 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 83B1785F13; Fri, 10 Mar 2023 15:10:48 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id A5CB785C9F; Fri, 10 Mar 2023 15:10:41 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id 24CC085D8F for ; Fri, 10 Mar 2023 15:10:36 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=abdellatif.elkhlifi@arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 21667C14; Fri, 10 Mar 2023 06:11:19 -0800 (PST) Received: from e130802.arm.com (unknown [10.57.64.115]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id F22B33F71A; Fri, 10 Mar 2023 06:10:32 -0800 (PST) From: Abdellatif El Khlifi To: sjg@chromium.org Cc: Drew.Reed@arm.com, abdellatif.elkhlifi@arm.com, achin.gupta@arm.com, ilias.apalodimas@linaro.org, jens.wiklander@linaro.org, nd@arm.com, robh@kernel.org, sudeep.holla@arm.com, trini@konsulko.com, u-boot@lists.denx.de, xueliang.zhong@arm.com Subject: [PATCH v9 02/10] lib: uuid: introduce uuid_str_to_le_bin function Date: Fri, 10 Mar 2023 14:10:08 +0000 Message-Id: <20230310141016.137986-3-abdellatif.elkhlifi@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> References: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean convert UUID string to little endian binary data Signed-off-by: Abdellatif El Khlifi Cc: Tom Rini Cc: Simon Glass Cc: Ilias Apalodimas Cc: Jens Wiklander Reviewed-by: Simon Glass --- Changelog: =============== v9: * add a full function prototype description in uuid.h v8: * use simple_strtoull() in uuid_str_to_le_bin() to support 32-bit platforms v7: * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin() * make uuid_str_to_le_bin() implementation similar to uuid_str_to_bin() by using same APIs v4: * rename ffa_uuid_str_to_bin to be_uuid_str_to_le_bin and put in a standalone commit (the current) v3: * introduce ffa_uuid_str_to_bin (provided by arm_ffa: introduce Arm FF-A low-level driver) include/uuid.h | 15 +++++++++++++++ lib/uuid.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/include/uuid.h b/include/uuid.h index 4a4883d3b5..89b93e642b 100644 --- a/include/uuid.h +++ b/include/uuid.h @@ -2,6 +2,10 @@ /* * Copyright (C) 2014 Samsung Electronics * Przemyslaw Marczak + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi */ #ifndef __UUID_H__ #define __UUID_H__ @@ -44,4 +48,15 @@ int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin); const char *uuid_guid_get_str(const unsigned char *guid_bin); void gen_rand_uuid(unsigned char *uuid_bin); void gen_rand_uuid_str(char *uuid_str, int str_format); + +/** + * uuid_str_to_le_bin() - Convert string UUID to little endian binary data. + * @uuid_str: pointer to UUID string + * @uuid_bin: pointer to allocated array for little endian output [16B] + * Return: + * uuid_bin filled with little endian UUID data + * On success 0 is returned. Otherwise, failure code. + */ +int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin); + #endif diff --git a/lib/uuid.c b/lib/uuid.c index 465e1ac38f..a72011e564 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -1,6 +1,10 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2011 Calxeda, Inc. + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi */ #include @@ -346,6 +350,50 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin, return 0; } +/** + * uuid_str_to_le_bin() - Convert string UUID to little endian binary data. + * @uuid_str: pointer to UUID string + * @uuid_bin: pointer to allocated array for little endian output [16B] + * + * UUID string is 36 characters (36 bytes): + * + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + * + * where x is a hexadecimal character. Fields are separated by '-'s. + * When converting to a little endian binary UUID, the string fields are reversed. + * + * Return: + * + * uuid_bin filled with little endian UUID data + * On success 0 is returned. Otherwise, failure code. + */ +int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin) +{ + u16 tmp16; + u32 tmp32; + u64 tmp64; + + if (!uuid_str_valid(uuid_str) || !uuid_bin) + return -EINVAL; + + tmp32 = cpu_to_le32(hextoul(uuid_str, NULL)); + memcpy(uuid_bin, &tmp32, 4); + + tmp16 = cpu_to_le16(hextoul(uuid_str + 9, NULL)); + memcpy(uuid_bin + 4, &tmp16, 2); + + tmp16 = cpu_to_le16(hextoul(uuid_str + 14, NULL)); + memcpy(uuid_bin + 6, &tmp16, 2); + + tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL)); + memcpy(uuid_bin + 8, &tmp16, 2); + + tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16)); + memcpy(uuid_bin + 10, &tmp64, 6); + + return 0; +} + /* * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID. * From patchwork Fri Mar 10 14:10:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdellatif El Khlifi X-Patchwork-Id: 1755240 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PY7JY5pd4z1yWl for ; Sat, 11 Mar 2023 01:11:25 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id EB5A885F35; Fri, 10 Mar 2023 15:10:53 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id 8983F85D94; Fri, 10 Mar 2023 15:10:42 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id DC42185D8D for ; Fri, 10 Mar 2023 15:10:38 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=abdellatif.elkhlifi@arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id DDA971515; Fri, 10 Mar 2023 06:11:21 -0800 (PST) Received: from e130802.arm.com (unknown [10.57.64.115]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id EAF1B3F71A; Fri, 10 Mar 2023 06:10:35 -0800 (PST) From: Abdellatif El Khlifi To: sjg@chromium.org Cc: Drew.Reed@arm.com, abdellatif.elkhlifi@arm.com, achin.gupta@arm.com, ilias.apalodimas@linaro.org, jens.wiklander@linaro.org, nd@arm.com, robh@kernel.org, sudeep.holla@arm.com, trini@konsulko.com, u-boot@lists.denx.de, xueliang.zhong@arm.com Subject: [PATCH v9 03/10] lib: uuid: introduce testcase for uuid_str_to_le_bin Date: Fri, 10 Mar 2023 14:10:09 +0000 Message-Id: <20230310141016.137986-4-abdellatif.elkhlifi@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> References: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean provide a test case Signed-off-by: Abdellatif El Khlifi Cc: Simon Glass --- MAINTAINERS | 5 +++++ test/lib/Makefile | 1 + test/lib/uuid.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 test/lib/uuid.c diff --git a/MAINTAINERS b/MAINTAINERS index e29c16cf01..58370c5fbd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1596,3 +1596,8 @@ S: Maintained F: arch/arm/dts/ls1021a-twr-u-boot.dtsi F: drivers/crypto/fsl/ F: include/fsl_sec.h + +UUID testing +M: Abdellatif El Khlifi +S: Maintained +F: test/lib/uuid.c diff --git a/test/lib/Makefile b/test/lib/Makefile index 7e7922fe3b..db6d88c065 100644 --- a/test/lib/Makefile +++ b/test/lib/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_UT_LIB_RSA) += rsa.o obj-$(CONFIG_AES) += test_aes.o obj-$(CONFIG_GETOPT) += getopt.o obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o +obj-$(CONFIG_LIB_UUID) += uuid.o else obj-$(CONFIG_SANDBOX) += kconfig_spl.o endif diff --git a/test/lib/uuid.c b/test/lib/uuid.c new file mode 100644 index 0000000000..6f24939de4 --- /dev/null +++ b/test/lib/uuid.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Functional tests for UCLASS_FFA class + * + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi + */ + +#include +#include +#include +#include +#include + +/* test UUID */ +#define TEST_SVC_UUID "ed32d533-4209-99e6-2d72-cdd998a79cc0" + +#define UUID_SIZE 16 + +/* The UUID binary data (little-endian format) */ +static const u8 ref_uuid_bin[UUID_SIZE] = { + 0x33, 0xd5, 0x32, 0xed, + 0x09, 0x42, 0xe6, 0x99, + 0x72, 0x2d, 0xc0, 0x9c, + 0xa7, 0x98, 0xd9, 0xcd +}; + +static int lib_test_uuid_to_le(struct unit_test_state *uts) +{ + const char *uuid_str = TEST_SVC_UUID; + u8 ret_uuid_bin[UUID_SIZE] = {0}; + int cnt; + + ut_assertok(uuid_str_to_le_bin(uuid_str, ret_uuid_bin)); + + for (cnt = 0; cnt < UUID_SIZE; cnt++) + ut_asserteq(ref_uuid_bin[cnt], ret_uuid_bin[cnt]); + + return 0; +} + +LIB_TEST(lib_test_uuid_to_le, 0); From patchwork Fri Mar 10 14:10:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdellatif El Khlifi X-Patchwork-Id: 1755244 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PY7KZ4wR5z1yWl for ; Sat, 11 Mar 2023 01:12:18 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id F2AA085F39; Fri, 10 Mar 2023 15:11:24 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id BBA0B85F22; Fri, 10 Mar 2023 15:11:13 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id 150BE85D95 for ; Fri, 10 Mar 2023 15:10:43 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=abdellatif.elkhlifi@arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B46B0C14; Fri, 10 Mar 2023 06:11:25 -0800 (PST) Received: from e130802.arm.com (unknown [10.57.64.115]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id B2EF63F71A; Fri, 10 Mar 2023 06:10:38 -0800 (PST) From: Abdellatif El Khlifi To: sjg@chromium.org Cc: Drew.Reed@arm.com, abdellatif.elkhlifi@arm.com, achin.gupta@arm.com, ilias.apalodimas@linaro.org, jens.wiklander@linaro.org, nd@arm.com, robh@kernel.org, sudeep.holla@arm.com, trini@konsulko.com, u-boot@lists.denx.de, xueliang.zhong@arm.com Subject: [PATCH v9 04/10] arm_ffa: introduce Arm FF-A low-level driver Date: Fri, 10 Mar 2023 14:10:10 +0000 Message-Id: <20230310141016.137986-5-abdellatif.elkhlifi@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> References: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Add the core driver 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_get_device_by_name). 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: - partition_info_get - sync_send_receive - rxtx_unmap 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 Cc: Tom Rini Cc: Simon Glass Cc: Ilias Apalodimas Cc: Jens Wiklander --- Changelog: =============== v9: * integrate the FF-A bus discovery in the DM and use ARM_SMCCC_FEATURES for binding v8: * make ffa_get_partitions_info() second argument to be an SP count in both modes * update ffa_bus_prvdata_get() to return a pointer rather than a pointer address * remove packing from ffa_partition_info and ffa_send_direct_data structures * pass the FF-A bus device to the bus operations v7: * add support for 32-bit direct messaging * rename be_uuid_str_to_le_bin() to uuid_str_to_le_bin() * improve the declaration of error handling mapping * stating in doc/arch/arm64.ffa.rst that EFI runtime is not supported v6: * drop use of EFI runtime support (We decided with Linaro to add this later) * drop discovery from initcalls (discovery will be on demand by FF-A users) * set the alignment of the RX/TX buffers to the larger translation granule size * move FF-A RX/TX buffers unmapping at ExitBootServices() to a separate commit * update the documentation and move it to doc/arch/arm64.ffa.rst v4: * add doc/README.ffa.drv * moving the FF-A driver work to drivers/firmware/arm-ffa * use less #ifdefs in lib/efi_loader/efi_boottime.c and replace #if defined by #if CONFIG_IS_ENABLED * improving error handling by mapping the FF-A errors to standard errors and logs * replacing panics with an error log and returning an error code * improving features discovery in FFA_FEATURES by introducing rxtx_min_pages private data field * add ffa_remove and ffa_unbind functions * improve how the driver behaves when bus discovery is done more than once v3: * align the interfaces of the U-Boot FF-A driver with those in the linux FF-A driver * remove the FF-A helper layer * make the U-Boot FF-A driver independent from EFI * provide an optional config that enables copying the driver data to EFI runtime section at ExitBootServices service * use 64-bit version of FFA_RXTX_MAP, FFA_MSG_SEND_DIRECT_{REQ, RESP} v2: * make FF-A bus discoverable using device_{bind, probe} APIs * remove device tree support v1: * introduce FF-A bus driver with device tree support MAINTAINERS | 7 + doc/arch/arm64.ffa.rst | 282 +++++ doc/arch/index.rst | 1 + drivers/Makefile | 1 + drivers/firmware/Kconfig | 1 + drivers/firmware/arm-ffa/Kconfig | 33 + drivers/firmware/arm-ffa/Makefile | 8 + drivers/firmware/arm-ffa/arm-ffa-uclass.c | 33 + drivers/firmware/arm-ffa/arm_ffa_priv.h | 209 ++++ drivers/firmware/arm-ffa/core.c | 1249 +++++++++++++++++++++ include/arm_ffa.h | 88 ++ include/dm/uclass-id.h | 6 + 12 files changed, 1918 insertions(+) create mode 100644 doc/arch/arm64.ffa.rst create mode 100644 drivers/firmware/arm-ffa/Kconfig create mode 100644 drivers/firmware/arm-ffa/Makefile create mode 100644 drivers/firmware/arm-ffa/arm-ffa-uclass.c create mode 100644 drivers/firmware/arm-ffa/arm_ffa_priv.h create mode 100644 drivers/firmware/arm-ffa/core.c create mode 100644 include/arm_ffa.h diff --git a/MAINTAINERS b/MAINTAINERS index 58370c5fbd..1dfa23c1f0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -266,6 +266,13 @@ 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 +S: Maintained +F: doc/arch/arm64.ffa.rst +F: drivers/firmware/arm-ffa/ +F: include/arm_ffa.h + ARM FREESCALE IMX M: Stefano Babic M: Fabio Estevam diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst new file mode 100644 index 0000000000..8fad9ef3d0 --- /dev/null +++ b/doc/arch/arm64.ffa.rst @@ -0,0 +1,282 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Arm FF-A Driver +=============== + +Summary +------- + +FF-A stands for Firmware Framework for Arm A-profile processors. + +FF-A specifies interfaces that enable a pair of software sandboxes to +communicate with each other. A sandbox aka partition could +be a VM in the Normal or Secure world, an application in S-EL0, or a +Trusted OS in S-EL1. + +This FF-A driver implements the interfaces to communicate with partitions in +the Secure world aka Secure partitions (SPs). + +The driver 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. + +FF-A driver 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 the FF-A driver supports EFI boot time only. + +Runtime support will be added in future developments. + +FF-A and SMC specifications +------------------------------------------- + +The current implementation of the driver relies on FF-A specification v1.0 +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 driver has been tested with OP-TEE which supports SMC32 calling convention. + +For more details please refer to the FF-A v1.0 spec: +https://documentation-service.arm.com/static/5fb7e8a6ca04df4095c1d65e?token= + +Hypervisors are supported if they are configured to trap SMC calls. + +The FF-A driver uses 64-bit registers as per SMCCCv1.2 specification. + +For more details please refer to the SMC Calling Convention v1.2 spec: +https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6?token= + +Supported hardware +-------------------------------- + +Aarch64 plaforms + +Configuration +---------------------- + +CONFIG_ARM_FFA_TRANSPORT + Enables the FF-A bus driver. Turn this on if you want to use FF-A + communication. + +FF-A ABIs under the hood +--------------------------------------- + +Invoking an FF-A ABI involves providing to the secure world/hypervisor the +expected arguments from the ABI. + +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 FF-A driver (non-secure world). + +The driver reads the response and processes it accordingly. + +This methodology applies to all the FF-A ABIs in the driver. + +FF-A bus discovery in U-Boot +------------------------------------------- + +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 ffa_bus_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 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 the DM class searching APIs +(e.g: uclass_get_device_by_name). Please refer to the armffa command implementation +as an example of how to probe and interact with the FF-A driver. + +When calling uclass_get_device_by_name() for example, the FF-A driver is probed +and ffa_probe() is called which performs the following: + + - allocating private data (priv) with devres + - updating priv with discovery information + - 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. + +FF-A device destruction +------------------------- + +When the FF-A device is removed by the DM, RX/TX buffers are automatically +unmapped and freed. Same happens when the device is unbound before being +removed first. + +For example, at EFI efi_exit_boot_services() active devices are automatically removed +by dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL). + +By consequence, the FF-A RX/TX are unmapped automatically. + +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 rxtx_unmap() and this is done +automatically at efi_exit_boot_services(). + +If RX/TX buffers created by U-Boot are not unmapped and by consequence becoming +available at EFI runtime, secure world will get confused about RX/TX buffers +ownership (U-Boot vs kernel). + +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. + +The bus driver layer +------------------------------ + +The driver comes on top of the SMCCC layer and is implemented in +drivers/firmware/arm-ffa/core.c + +The driver provides the following features: + +- 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, the driver takes care of how to transport + that to the secure world/hypervisor using FF-A + +- The driver provides callbacks to be used by clients to access the FF-A bus: + + - partition_info_get + - sync_send_receive + - 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 + +The armffa command +----------------------------------- + +armffa is an implementation defined command showcasing how to use the FF-A driver and how to invoke +its operations. + +Please refer the command documentation at doc/usage/cmd/armffa.rst + +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 (Mar 07 2023 - 11:05:21 +0000) corstone1000 aarch64 + + DRAM: 2 GiB + [FFA] trying FF-A framework discovery + [FFA] Conduit is SMC + [FFA] FF-A driver 1.0 + FF-A framework 1.0 + [FFA] Versions are compatible + Core: 18 devices, 12 uclasses, devicetree: separate + MMC: + Loading Environment from nowhere... OK + ... + Hit any key to stop autoboot: 0 + Loading kernel from 0x083EE000 to memory ... + ... + [FFA] endpoint ID is 0 + [FFA] Using 1 4KB page(s) for RX/TX buffers size + [FFA] RX buffer at virtual address 00000000fdf4e000 + [FFA] TX buffer at virtual address 00000000fdf50000 + [FFA] RX/TX buffers mapped + [FFA] Reading partitions data from the RX buffer + [FFA] Partition ID 8001 : info cached + [FFA] Partition ID 8002 : info cached + [FFA] Partition ID 8003 : info cached + [FFA] 3 partition(s) found and cached + [FFA] Preparing for checking partitions count + [FFA] Searching partitions using the provided UUID + [FFA] No partition found. Querying framework ... + [FFA] Reading partitions data from the RX buffer + [FFA] Number of partition(s) matching the UUID: 1 + EFI: Pre-allocating 1 partition(s) info structures + [FFA] Preparing for filling partitions info + [FFA] Searching partitions using the provided UUID + [FFA] Partition ID 8003 matches the provided UUID + EFI: MM partition ID 0x8003 + EFI: Corstone1000: Capsule shared buffer at 0x80000000 , size 8192 pages + Booting /MemoryMapped(0x0,0x88200000,0xf00000) + EFI stub: Booting Linux Kernel... + EFI stub: Using DTB from configuration table + EFI stub: Exiting boot services... + [FFA] removing the device + [FFA] unmapping RX/TX buffers + [FFA] Freeing RX/TX buffers + Booting Linux on physical CPU 0x0000000000 [0x411fd040] + 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 + efi: EFI v2.100 by Das U-Boot + ... + +Contributors +------------ + * Abdellatif El Khlifi diff --git a/doc/arch/index.rst b/doc/arch/index.rst index b8da4b8c8e..2f916f4026 100644 --- a/doc/arch/index.rst +++ b/doc/arch/index.rst @@ -8,6 +8,7 @@ Architecture-specific doc arc arm64 + arm64.ffa m68k mips nios2 diff --git a/drivers/Makefile b/drivers/Makefile index 58be410135..885fdef4dc 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -112,6 +112,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/ diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index eae1c8ddc9..8789b1ea14 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -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" diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig new file mode 100644 index 0000000000..e5b2912201 --- /dev/null +++ b/drivers/firmware/arm-ffa/Kconfig @@ -0,0 +1,33 @@ +# 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. + + This driver 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). + This FF-A driver takes care of all the interactions between Normal world + and Secure World. + + For more details about the FF-A driver, please refer to doc/arch/arm64.ffa.rst + diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile new file mode 100644 index 0000000000..c8d83b4bc9 --- /dev/null +++ b/drivers/firmware/arm-ffa/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2022-2023 Arm Limited and/or its affiliates +# +# Authors: +# Abdellatif El Khlifi + +obj-y += arm-ffa-uclass.o core.o diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c new file mode 100644 index 0000000000..bc4fe68d57 --- /dev/null +++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi + */ + +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/** + * ffa_bus_get_ops() - bus driver operations getter + * @dev: the arm_ffa device + * Returns a pointer to the FF-A driver ops field. + * Return: + * The ops pointer on success, NULL on failure. + */ +const struct ffa_bus_ops *ffa_bus_get_ops(struct udevice *dev) +{ + if (!dev) + return NULL; + + return device_get_ops(dev); +} + +UCLASS_DRIVER(ffa) = { + .name = "ffa", + .id = UCLASS_FFA, +}; diff --git a/drivers/firmware/arm-ffa/arm_ffa_priv.h b/drivers/firmware/arm-ffa/arm_ffa_priv.h new file mode 100644 index 0000000000..51df7d1c64 --- /dev/null +++ b/drivers/firmware/arm-ffa/arm_ffa_priv.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi + */ + +#ifndef __ARM_FFA_PRV_H +#define __ARM_FFA_PRV_H + +#include +#include +#include +#include + +/* This header is exclusively used by the FF-A core driver, sandbox driver and sandbox tests */ + +/* FF-A core driver name */ +#define FFA_DRV_NAME "arm_ffa" + +/* The FF-A SMC function definitions */ + +#if CONFIG_IS_ENABLED(SANDBOX_FFA) +#include "sandbox_arm_ffa.h" +#else +/* CONFIG_ARM64 */ +#include +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 +}; + +/* 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) + +/* + * 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 */ +}; + +/** + * 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 - 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_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_discovery_info - discovery information + * @fwk_version: FF-A framework version + * @invoke_ffa_fn: The function executing the FF-A function (ABI) + */ +struct ffa_discovery_info { + u32 fwk_version; + invoke_ffa_fn_t invoke_ffa_fn; +}; + +/** + * struct ffa_priv - the driver private data structure + * + * @dscvry_info: Initial information discovered + * @ops: The driver operations structure + * @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. + * The data is dynamically allocated, managed by devres + * and registered with the DM. + */ +struct ffa_priv { + struct ffa_discovery_info dscvry_info; + struct ffa_bus_ops ops; + u16 id; + struct ffa_partitions partitions; + struct ffa_rxtxpair pair; +}; +#endif diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c new file mode 100644 index 0000000000..2210f5343c --- /dev/null +++ b/drivers/firmware/arm-ffa/core.c @@ -0,0 +1,1249 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "arm_ffa_priv.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* FF-A discovery information */ +struct ffa_discovery_info dscvry_info; + +/* The function that sets the SMC conduit */ +static int ffa_set_smc_conduit(void); + +/* Error mapping declarations */ + +int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = { + [NOT_SUPPORTED] = -EOPNOTSUPP, + [INVALID_PARAMETERS] = -EINVAL, + [NO_MEMORY] = -ENOMEM, + [BUSY] = -EBUSY, + [INTERRUPTED] = -EINTR, + [DENIED] = -EACCES, + [RETRY] = -EAGAIN, + [ABORTED] = -ECANCELED, +}; + +struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = { + [FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = { + { + [NOT_SUPPORTED] = + "NOT_SUPPORTED: A Firmware Framework implementation does not exist", + }, + }, + [FFA_ID_TO_ERRMAP_ID(FFA_ID_GET)] = { + { + [NOT_SUPPORTED] = + "NOT_SUPPORTED: This function is not implemented at this FF-A instance", + }, + }, + [FFA_ID_TO_ERRMAP_ID(FFA_FEATURES)] = { + { + [NOT_SUPPORTED] = + "NOT_SUPPORTED: FFA_RXTX_MAP is not implemented at this FF-A instance", + }, + }, + [FFA_ID_TO_ERRMAP_ID(FFA_PARTITION_INFO_GET)] = { + { + [NOT_SUPPORTED] = + "NOT_SUPPORTED: This function is not implemented at this FF-A instance", + [INVALID_PARAMETERS] = + "INVALID_PARAMETERS: Unrecognized UUID", + [NO_MEMORY] = + "NO_MEMORY: Results cannot fit in RX buffer of the caller", + [BUSY] = + "BUSY: RX buffer of the caller is not free", + [DENIED] = + "DENIED: Callee is not in a state to handle this request", + }, + }, + [FFA_ID_TO_ERRMAP_ID(FFA_RXTX_UNMAP)] = { + { + [NOT_SUPPORTED] = + "NOT_SUPPORTED: FFA_RXTX_UNMAP is not implemented at this FF-A instance", + [INVALID_PARAMETERS] = + "INVALID_PARAMETERS: No buffer pair registered on behalf of the caller", + }, + }, + [FFA_ID_TO_ERRMAP_ID(FFA_RX_RELEASE)] = { + { + [NOT_SUPPORTED] = + "NOT_SUPPORTED: FFA_RX_RELEASE is not implemented at this FF-A instance", + [DENIED] = + "DENIED: Caller did not have ownership of the RX buffer", + }, + }, + [FFA_ID_TO_ERRMAP_ID(FFA_RXTX_MAP)] = { + { + [NOT_SUPPORTED] = + "NOT_SUPPORTED: This function is not implemented at this FF-A instance", + [INVALID_PARAMETERS] = + "INVALID_PARAMETERS: Field(s) in input parameters incorrectly encoded", + [NO_MEMORY] = + "NO_MEMORY: Not enough memory", + [DENIED] = + "DENIED: Buffer pair already registered", + }, + }, +}; + +/** + * ffa_to_std_errno() - convert FF-A error code to standard error code + * @ffa_errno: Error code returned by the FF-A ABI + * + * This function maps the given FF-A error code as specified + * by the spec to a u-boot standard error code. + * + * Return: + * + * The standard error code on success. . Otherwise, failure + */ +int ffa_to_std_errno(int ffa_errno) +{ + int err_idx = -ffa_errno; + + /* Map the FF-A error code to the standard u-boot error code */ + if (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR) + return ffa_to_std_errmap[err_idx]; + return -EINVAL; +} + +/** + * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI + * @ffa_id: FF-A ABI ID + * @ffa_errno: Error code returned by the FF-A ABI + * + * This function maps the FF-A error code to the error log relevant to the + * selected FF-A ABI. Then the error log is printed. + * + * Return: + * + * 0 on success. . Otherwise, failure + */ +int ffa_print_error_log(u32 ffa_id, int ffa_errno) +{ + int err_idx = -ffa_errno, abi_idx = 0; + + /* Map the FF-A error code to the corresponding error log */ + + if (err_idx <= 0 || err_idx >= MAX_NUMBER_FFA_ERR) + return -EINVAL; + + if (ffa_id < FFA_FIRST_ID || ffa_id > FFA_LAST_ID) + return -EINVAL; + + abi_idx = FFA_ID_TO_ERRMAP_ID(ffa_id); + if (abi_idx < 0 || abi_idx >= FFA_ERRMAP_COUNT) + return -EINVAL; + + if (!err_msg_map[abi_idx].err_str[err_idx]) + return -EINVAL; + + log_err("[FFA] %s\n", err_msg_map[abi_idx].err_str[err_idx]); + + return 0; +} + +/* Driver core functions */ + +/** + * ffa_get_version() - FFA_VERSION handler function + * + * This function implements 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 + */ +static int ffa_get_version(void) +{ + u16 major, minor; + ffa_value_t res = {0}; + int ffa_errno; + + if (!dscvry_info.invoke_ffa_fn) + return -EINVAL; + + dscvry_info.invoke_ffa_fn((ffa_value_t){ + .a0 = FFA_SMC_32(FFA_VERSION), .a1 = FFA_VERSION_1_0, + }, &res); + + ffa_errno = res.a0; + if (ffa_errno < 0) { + ffa_print_error_log(FFA_VERSION, ffa_errno); + return ffa_to_std_errno(ffa_errno); + } + + major = GET_FFA_MAJOR_VERSION(res.a0); + minor = GET_FFA_MINOR_VERSION(res.a0); + + log_info("[FFA] FF-A driver %d.%d\nFF-A framework %d.%d\n", + FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor); + + if (major == FFA_MAJOR_VERSION && minor >= FFA_MINOR_VERSION) { + log_info("[FFA] Versions are compatible\n"); + + dscvry_info.fwk_version = res.a0; + + return 0; + } + + log_err("[FFA] versions are incompatible\nExpected: %d.%d , Found: %d.%d\n", + FFA_MAJOR_VERSION, FFA_MINOR_VERSION, major, minor); + + return -EPROTONOSUPPORT; +} + +/** + * ffa_get_endpoint_id() - FFA_ID_GET handler function + * @dev: The FF-A bus device + * + * This function implements FFA_ID_GET FF-A function + * to get from the secure world u-boot endpoint ID + * + * Return: + * + * 0 on success. Otherwise, failure + */ +static int ffa_get_endpoint_id(struct udevice *dev) +{ + ffa_value_t res = {0}; + int ffa_errno; + struct ffa_priv *priv = dev_get_priv(dev); + + priv->dscvry_info.invoke_ffa_fn((ffa_value_t){ + .a0 = FFA_SMC_32(FFA_ID_GET), + }, &res); + + if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { + priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2); + log_info("[FFA] endpoint ID is %u\n", priv->id); + + return 0; + } + + ffa_errno = res.a2; + + ffa_print_error_log(FFA_ID_GET, ffa_errno); + + return ffa_to_std_errno(ffa_errno); +} + +/** + * ffa_set_rxtx_buffers_pages_cnt() - sets the minimum number of pages in each of the RX/TX buffers + * @dev: The FF-A bus device + * @prop_field: properties field obtained from FFA_FEATURES ABI + * + * This function sets the minimum number of pages + * in each of the RX/TX buffers in the private data structure + * + * Return: + * + * buf_4k_pages points to the returned number of pages + * 0 on success. Otherwise, failure + */ +static int ffa_set_rxtx_buffers_pages_cnt(struct udevice *dev, u32 prop_field) +{ + struct ffa_priv *priv = dev_get_priv(dev); + + switch (prop_field) { + case RXTX_4K: + priv->pair.rxtx_min_pages = 1; + break; + case RXTX_16K: + priv->pair.rxtx_min_pages = 4; + break; + case RXTX_64K: + priv->pair.rxtx_min_pages = 16; + break; + default: + log_err("[FFA] RX/TX buffer size not supported\n"); + return -EINVAL; + } + + return 0; +} + +/** + * ffa_get_rxtx_map_features() - FFA_FEATURES handler function with FFA_RXTX_MAP argument + * @dev: The FF-A bus device + * + * This function implements FFA_FEATURES FF-A function + * to retrieve the FFA_RXTX_MAP features + * + * Return: + * + * 0 on success. Otherwise, failure + */ +static int ffa_get_rxtx_map_features(struct udevice *dev) +{ + ffa_value_t res = {0}; + int ffa_errno; + struct ffa_priv *priv = dev_get_priv(dev); + + priv->dscvry_info.invoke_ffa_fn((ffa_value_t){ + .a0 = FFA_SMC_32(FFA_FEATURES), + .a1 = FFA_SMC_64(FFA_RXTX_MAP), + }, &res); + + if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) + return ffa_set_rxtx_buffers_pages_cnt(dev, res.a2); + + ffa_errno = res.a2; + ffa_print_error_log(FFA_FEATURES, ffa_errno); + + return ffa_to_std_errno(ffa_errno); +} + +/** + * ffa_free_rxtx_buffers() - frees the RX/TX buffers + * @dev: The FF-A bus device + * + * This function frees the RX/TX buffers + */ +static void ffa_free_rxtx_buffers(struct udevice *dev) +{ + struct ffa_priv *priv = dev_get_priv(dev); + + log_info("[FFA] Freeing RX/TX buffers\n"); + + if (priv->pair.rxbuf) { + free(priv->pair.rxbuf); + priv->pair.rxbuf = NULL; + } + + if (priv->pair.txbuf) { + free(priv->pair.txbuf); + priv->pair.txbuf = NULL; + } +} + +/** + * ffa_alloc_rxtx_buffers() - allocates the RX/TX buffers + * @dev: The FF-A bus device + * + * This function is used by ffa_map_rxtx_buffers to allocate + * the RX/TX buffers before mapping them. The allocated memory is physically + * contiguous since memalign ends up calling malloc which allocates + * contiguous memory in u-boot. + * + * Return: + * + * 0 on success. Otherwise, failure + */ +static int ffa_alloc_rxtx_buffers(struct udevice *dev) +{ + u64 bytes; + struct ffa_priv *priv = dev_get_priv(dev); + + log_info("[FFA] Using %lu 4KB page(s) for RX/TX buffers size\n", + priv->pair.rxtx_min_pages); + + bytes = priv->pair.rxtx_min_pages * SZ_4K; + + /* + * The alignment of the RX and TX buffers must be equal + * to the larger translation granule size + * Assumption: Memory allocated with memalign is always physically contiguous + */ + + priv->pair.rxbuf = memalign(bytes, bytes); + if (!priv->pair.rxbuf) { + log_err("[FFA] failure to allocate RX buffer\n"); + return -ENOBUFS; + } + + log_info("[FFA] RX buffer at virtual address %p\n", priv->pair.rxbuf); + + priv->pair.txbuf = memalign(bytes, bytes); + if (!priv->pair.txbuf) { + free(priv->pair.rxbuf); + priv->pair.rxbuf = NULL; + log_err("[FFA] failure to allocate the TX buffer\n"); + return -ENOBUFS; + } + + log_info("[FFA] TX buffer at virtual address %p\n", priv->pair.txbuf); + + /* Make sure the buffers are cleared before use */ + memset(priv->pair.rxbuf, 0, bytes); + memset(priv->pair.txbuf, 0, bytes); + + return 0; +} + +/** + * ffa_map_rxtx_buffers() - FFA_RXTX_MAP handler function + * @dev: The FF-A bus device + * + * This function implements FFA_RXTX_MAP FF-A function + * to map the RX/TX buffers + * + * Return: + * + * 0 on success. Otherwise, failure + */ +static int ffa_map_rxtx_buffers(struct udevice *dev) +{ + int ret; + ffa_value_t res = {0}; + int ffa_errno; + struct ffa_priv *priv = dev_get_priv(dev); + + ret = ffa_alloc_rxtx_buffers(dev); + if (ret) + return ret; + + /* + * we need to pass the physical addresses of the RX/TX buffers + * in u-boot physical/virtual mapping is 1:1 + * no need to convert from virtual to physical + */ + + priv->dscvry_info.invoke_ffa_fn((ffa_value_t){ + .a0 = FFA_SMC_64(FFA_RXTX_MAP), + .a1 = map_to_sysmem(priv->pair.txbuf), + .a2 = map_to_sysmem(priv->pair.rxbuf), + .a3 = priv->pair.rxtx_min_pages, + }, &res); + + if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { + log_info("[FFA] RX/TX buffers mapped\n"); + return 0; + } + + ffa_errno = res.a2; + ffa_print_error_log(FFA_RXTX_MAP, ffa_errno); + + ffa_free_rxtx_buffers(dev); + + return ffa_to_std_errno(ffa_errno); +} + +/** + * ffa_unmap_rxtx_buffers() - 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 + */ +static int ffa_unmap_rxtx_buffers(struct udevice *dev) +{ + ffa_value_t res = {0}; + int ffa_errno; + struct ffa_priv *priv = NULL; + + if (!dev) + return -ENODEV; + + log_info("[FFA] unmapping RX/TX buffers\n"); + + priv = dev_get_priv(dev); + + priv->dscvry_info.invoke_ffa_fn((ffa_value_t){ + .a0 = FFA_SMC_32(FFA_RXTX_UNMAP), + .a1 = PREP_SELF_ENDPOINT_ID(priv->id), + }, &res); + + if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { + ffa_free_rxtx_buffers(dev); + return 0; + } + + ffa_errno = res.a2; + ffa_print_error_log(FFA_RXTX_UNMAP, ffa_errno); + + return ffa_to_std_errno(ffa_errno); +} + +/** + * ffa_release_rx_buffer() - FFA_RX_RELEASE handler function + * @dev: The FF-A bus device + * + * This function invokes FFA_RX_RELEASE FF-A function + * to release the ownership of the RX buffer + * + * Return: + * + * 0 on success. Otherwise, failure + */ +static int ffa_release_rx_buffer(struct udevice *dev) +{ + ffa_value_t res = {0}; + int ffa_errno; + struct ffa_priv *priv = dev_get_priv(dev); + + priv->dscvry_info.invoke_ffa_fn((ffa_value_t){ + .a0 = FFA_SMC_32(FFA_RX_RELEASE), + }, &res); + + if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) + return 0; + + ffa_errno = res.a2; + ffa_print_error_log(FFA_RX_RELEASE, ffa_errno); + + return ffa_to_std_errno(ffa_errno); +} + +/** + * ffa_uuid_are_identical() - checks whether two given UUIDs are identical + * @uuid1: first UUID + * @uuid2: second UUID + * + * This function is used by ffa_read_partitions_info to search + * for a UUID in the partitions descriptors table + * + * Return: + * + * 1 when UUIDs match. Otherwise, 0 + */ +bool ffa_uuid_are_identical(const struct ffa_partition_uuid *uuid1, + const struct ffa_partition_uuid *uuid2) +{ + if (!uuid1 || !uuid2) + return 0; + + return !memcmp(uuid1, uuid2, sizeof(struct ffa_partition_uuid)); +} + +/** + * ffa_read_partitions_info() - reads queried partition data + * @dev: The arm_ffa bus device + * @count: The number of partitions queried + * @part_uuid: Pointer to the partition(s) UUID + * + * This function reads the partitions information + * returned by the FFA_PARTITION_INFO_GET and saves it in the private + * data structure. + * + * Return: + * + * The private data structure is updated with the partition(s) information + * 0 is returned on success. Otherwise, failure + */ +static int ffa_read_partitions_info(struct udevice *dev, u32 count, + struct ffa_partition_uuid *part_uuid) +{ + struct ffa_priv *priv = dev_get_priv(dev); + + if (!count) { + log_err("[FFA] no partition detected\n"); + return -ENODATA; + } + + log_info("[FFA] Reading partitions data from the RX buffer\n"); + + if (!part_uuid) { + /* Querying information of all partitions */ + u64 buf_bytes; + u64 data_bytes; + u32 desc_idx; + struct ffa_partition_info *parts_info; + + data_bytes = count * sizeof(struct ffa_partition_desc); + + buf_bytes = priv->pair.rxtx_min_pages * SZ_4K; + + if (data_bytes > buf_bytes) { + log_err("[FFA] partitions data size exceeds the RX buffer size:\n"); + log_err("[FFA] sizes in bytes: data %llu , RX buffer %llu\n", + data_bytes, + buf_bytes); + + return -ENOMEM; + } + + priv->partitions.descs = devm_kmalloc(dev, data_bytes, __GFP_ZERO); + if (!priv->partitions.descs) { + log_err("[FFA] cannot allocate partitions data buffer\n"); + return -ENOMEM; + } + + parts_info = priv->pair.rxbuf; + + for (desc_idx = 0 ; desc_idx < count ; desc_idx++) { + priv->partitions.descs[desc_idx].info = + parts_info[desc_idx]; + + log_info("[FFA] Partition ID %x : info cached\n", + priv->partitions.descs[desc_idx].info.id); + } + + priv->partitions.count = count; + + log_info("[FFA] %d partition(s) found and cached\n", count); + + } else { + u32 rx_desc_idx, cached_desc_idx; + struct ffa_partition_info *parts_info; + u8 desc_found; + + parts_info = priv->pair.rxbuf; + + /* + * Search for the SP IDs read from the RX buffer + * in the already cached SPs. + * Update the UUID when ID found. + */ + for (rx_desc_idx = 0; rx_desc_idx < count ; rx_desc_idx++) { + desc_found = 0; + + /* Search the current ID in the cached partitions */ + for (cached_desc_idx = 0; + cached_desc_idx < priv->partitions.count; + cached_desc_idx++) { + /* Save the UUID */ + if (priv->partitions.descs[cached_desc_idx].info.id == + parts_info[rx_desc_idx].id) { + priv->partitions.descs[cached_desc_idx].sp_uuid = + *part_uuid; + + desc_found = 1; + break; + } + } + + if (!desc_found) + return -ENODATA; + } + } + + return 0; +} + +/** + * ffa_query_partitions_info() - invokes FFA_PARTITION_INFO_GET and saves partitions data + * @dev: The arm_ffa bus device + * @part_uuid: Pointer to the partition(s) UUID + * @pcount: Pointer to the number of partitions variable filled when querying + * + * This function executes the FFA_PARTITION_INFO_GET + * to query the partitions data. Then, it calls ffa_read_partitions_info + * to save the data in the private data structure. + * + * After reading the data the RX buffer is released using ffa_release_rx_buffer + * + * Return: + * + * When part_uuid is NULL, all partitions data are retrieved from secure world + * When part_uuid is non NULL, data for partitions matching the given UUID are + * retrieved and the number of partitions is returned + * 0 is returned on success. Otherwise, failure + */ +static int ffa_query_partitions_info(struct udevice *dev, struct ffa_partition_uuid *part_uuid, + u32 *pcount) +{ + struct ffa_partition_uuid query_uuid = {0}; + ffa_value_t res = {0}; + int ffa_errno; + struct ffa_priv *priv = dev_get_priv(dev); + + /* + * If a UUID is specified. Information for one or more + * partitions in the system is queried. Otherwise, information + * for all installed partitions is queried + */ + + if (part_uuid) { + if (!pcount) + return -EINVAL; + + query_uuid = *part_uuid; + } else if (pcount) { + return -EINVAL; + } + + priv->dscvry_info.invoke_ffa_fn((ffa_value_t){ + .a0 = FFA_SMC_32(FFA_PARTITION_INFO_GET), + .a1 = query_uuid.a1, + .a2 = query_uuid.a2, + .a3 = query_uuid.a3, + .a4 = query_uuid.a4, + }, &res); + + if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { + int ret; + + /* + * res.a2 contains the count of partition information descriptors + * populated in the RX buffer + */ + if (res.a2) { + ret = ffa_read_partitions_info(dev, (u32)res.a2, part_uuid); + if (ret) { + log_err("[FFA] failed reading SP(s) data , err (%d)\n", ret); + ffa_release_rx_buffer(dev); + return -EINVAL; + } + } + + /* Return the SP count (when querying using a UUID) */ + if (pcount) + *pcount = (u32)res.a2; + + /* + * After calling FFA_PARTITION_INFO_GET the buffer ownership + * is assigned to the consumer (u-boot). So, we need to give + * the ownership back to the SPM or hypervisor + */ + ret = ffa_release_rx_buffer(dev); + + return ret; + } + + ffa_errno = res.a2; + ffa_print_error_log(FFA_PARTITION_INFO_GET, ffa_errno); + + return ffa_to_std_errno(ffa_errno); +} + +/** + * ffa_get_partitions_info() - FFA_PARTITION_INFO_GET handler function + * + * The passed arguments: + * Mode 1: When getting from the driver the number of + * secure partitions: + * @uuid_str: pointer to the UUID string + * @sp_count: pointer to the variable that contains the number of partitions + * The variable will be set by the driver + * @buffer: NULL + * + * Mode 2: When requesting the driver to return the + * partitions information: + * @dev: The arm_ffa bus device + * @uuid_str: pointer to the UUID string + * @sp_count: pointer to the variable that contains the number of empty partition descriptors + * The variable will be read by the driver + * @buffer: pointer to SPs information buffer + * (allocated by the client and contains empty @sp_count descriptors). + * The buffer will be filled by the driver + * + * This function queries the secure partition data from + * the private data structure. If not found, it invokes 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 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(). + * + * When invoked through a client request, ffa_get_partitions_info should be + * called twice. First call is to get from the driver the number of secure + * partitions (SPs) associated to a particular UUID. + * Then, the caller (client) allocates the buffer to host the SPs data and + * issues a 2nd call. Then, the driver fills the SPs data in the pre-allocated + * buffer. + * + * To achieve the mechanism described above, ffa_get_partitions_info uses the + * following functions: + * ffa_read_partitions_info + * ffa_query_partitions_info + * + * Return: + * + * @sp_count: When pointing to the number of partitions variable, the number is + * set by the driver. + * When pointing to the partitions information buffer size, the buffer will be + * filled by the driver. + * + * On success 0 is returned. Otherwise, failure + */ +static int ffa_get_partitions_info(struct udevice *dev, const char *uuid_str, + u32 *sp_count, struct ffa_partition_info *buffer) +{ + /* + * fill_data: + * 0: return the SP count + * 1: fill SP data and return it to the caller + */ + bool fill_data = 0; + u32 desc_idx, client_desc_idx; + struct ffa_partition_uuid part_uuid = {0}; + u32 sp_found = 0; + struct ffa_priv *priv = NULL; + + if (!dev) + return -ENODEV; + + priv = dev_get_priv(dev); + + if (!priv->partitions.count || !priv->partitions.descs) { + log_err("[FFA] no partition installed\n"); + return -EINVAL; + } + + if (!uuid_str) { + log_err("[FFA] no UUID provided\n"); + return -EINVAL; + } + + if (!sp_count) { + log_err("[FFA] no size/count provided\n"); + return -EINVAL; + } + + if (uuid_str_to_le_bin(uuid_str, (unsigned char *)&part_uuid)) { + log_err("[FFA] invalid UUID\n"); + return -EINVAL; + } + + if (!buffer) { + /* Mode 1: getting the number of secure partitions */ + + fill_data = 0; + + log_info("[FFA] Preparing for checking partitions count\n"); + + } else if (*sp_count) { + /* Mode 2: retrieving the partitions information */ + + fill_data = 1; + + client_desc_idx = 0; + + log_info("[FFA] Preparing for filling partitions info\n"); + + } else { + log_err("[FFA] invalid function arguments provided\n"); + return -EINVAL; + } + + log_info("[FFA] Searching partitions using the provided UUID\n"); + + /* Search in the cached partitions */ + for (desc_idx = 0; + desc_idx < priv->partitions.count; + desc_idx++) { + if (ffa_uuid_are_identical(&priv->partitions.descs[desc_idx].sp_uuid, + &part_uuid)) { + log_info("[FFA] Partition ID %x matches the provided UUID\n", + priv->partitions.descs[desc_idx].info.id); + + sp_found++; + + if (fill_data) { + /* Trying to fill the partition info in the input buffer */ + + if (client_desc_idx < *sp_count) { + buffer[client_desc_idx++] = + priv->partitions.descs[desc_idx].info; + continue; + } + + log_err("[FFA] failed to fill client descriptor, buffer full\n"); + return -ENOBUFS; + } + } + } + + if (!sp_found) { + int ret; + + log_info("[FFA] No partition found. Querying framework ...\n"); + + ret = ffa_query_partitions_info(dev, &part_uuid, &sp_found); + + if (ret == 0) { + if (!fill_data) { + *sp_count = sp_found; + + log_info("[FFA] Number of partition(s) matching the UUID: %d\n", + sp_found); + } else { + /* + * If SPs data detected, they are already in the private data + * structure, retry searching SP data again to return them + * to the caller + */ + if (sp_found) + ret = ffa_get_partitions_info(dev, uuid_str, sp_count, + buffer); + else + ret = -ENODATA; + } + } + + return ret; + } + + /* Partition(s) found */ + if (!fill_data) + *sp_count = sp_found; + + return 0; +} + +/** + * ffa_cache_partitions_info() - Queries and saves all secure partitions data + * @dev: The arm_ffa bus device + * + * This function invokes FFA_PARTITION_INFO_GET FF-A + * function to query from secure world all partitions information. + * + * The FFA_PARTITION_INFO_GET call is issued with nil UUID as an argument. + * All installed partitions information are returned. We cache them in the + * resident private data structure and we keep the UUID field empty + * (in FF-A 1.0 UUID is not provided by the partition descriptor) + * + * This function is called at the device probing level. + * ffa_cache_partitions_info uses ffa_query_partitions_info to get the data + * + * Return: + * + * 0 on success. Otherwise, failure + */ +static int ffa_cache_partitions_info(struct udevice *dev) +{ + return ffa_query_partitions_info(dev, NULL, NULL); +} + +/** + * ffa_msg_send_direct_req() - 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 + */ +static int ffa_msg_send_direct_req(struct udevice *dev, u16 dst_part_id, + struct ffa_send_direct_data *msg, bool is_smc64) +{ + ffa_value_t res = {0}; + int ffa_errno; + u64 req_mode, resp_mode; + struct ffa_priv *priv = NULL; + + if (!dev) + return -ENODEV; + + priv = dev_get_priv(dev); + + if (!priv || !priv->dscvry_info.invoke_ffa_fn) + return -EINVAL; + + /* No partition installed */ + if (!priv->partitions.count || !priv->partitions.descs) + return -ENODEV; + + if (is_smc64) { + req_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ); + resp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP); + } else { + req_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ); + resp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP); + } + + priv->dscvry_info.invoke_ffa_fn((ffa_value_t){ + .a0 = req_mode, + .a1 = PREP_SELF_ENDPOINT_ID(priv->id) | + PREP_PART_ENDPOINT_ID(dst_part_id), + .a2 = 0, + .a3 = msg->data0, + .a4 = msg->data1, + .a5 = msg->data2, + .a6 = msg->data3, + .a7 = msg->data4, + }, &res); + + while (res.a0 == FFA_SMC_32(FFA_INTERRUPT)) + priv->dscvry_info.invoke_ffa_fn((ffa_value_t){ + .a0 = FFA_SMC_32(FFA_RUN), + .a1 = res.a1, + }, &res); + + if (res.a0 == FFA_SMC_32(FFA_SUCCESS)) { + /* Message sent with no response */ + return 0; + } + + if (res.a0 == resp_mode) { + /* Message sent with response extract the return data */ + msg->data0 = res.a3; + msg->data1 = res.a4; + msg->data2 = res.a5; + msg->data3 = res.a6; + msg->data4 = res.a7; + + return 0; + } + + ffa_errno = res.a2; + return ffa_to_std_errno(ffa_errno); +} + +/** + * ffa_try_discovery() - performs FF-A discovery + * Tries 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. + */ +bool ffa_try_discovery(void) +{ + int ret; + + log_info("[FFA] trying FF-A framework discovery\n"); + + ret = ffa_set_smc_conduit(); + if (ret) + return false; + + ret = ffa_get_version(); + if (ret) + return false; + + return true; +} + +/** + * __arm_ffa_fn_smc() - 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 __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res) +{ + arm_smccc_1_2_smc(&args, res); +} + +/** + * ffa_bus_is_supported() - FF-A discovery callback + * @invoke_fn: legacy SMC invoke function (not used) + * + * This function performs FF-A discovery by calling ffa_try_discovery(). + * 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 ffa_bus_is_supported(void (*invoke_fn)(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long a4, unsigned long a5, + unsigned long a6, unsigned long a7, + struct arm_smccc_res *res)) +{ + return ffa_try_discovery(); +} + +/* Registering the FF-A driver as an SMCCC feature driver */ + +ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = { + .driver_name = FFA_DRV_NAME, + .is_supported = ffa_bus_is_supported, +}; + +/** + * ffa_set_smc_conduit() - Set the SMC conduit + * + * This function selects the SMC conduit by setting the driver invoke function + * to SMC assembly function + * + * Return: + * + * 0 on success. Otherwise, failure + */ +static int ffa_set_smc_conduit(void) +{ + dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc; + + log_info("[FFA] Conduit is SMC\n"); + + return 0; +} + +/** + * ffa_devm_alloc_priv() - allocate FF-A driver private data + * @dev: The FF-A bus device + * + * This function dynamically allocates with devres the private data structure + * which contains all the FF-A data. Then, register the structure with the DM. + * Return: + * + * 0 on success. Otherwise, failure + */ +static int ffa_devm_alloc_priv(struct udevice *dev) +{ + struct ffa_priv *priv = dev_get_priv(dev); + + if (!priv) { + priv = devm_kmalloc(dev, sizeof(struct ffa_priv), __GFP_ZERO); + if (!priv) { + log_err("[FFA] can not allocate FF-A main data structure\n"); + return -ENOMEM; + } + dev_set_priv(dev, priv); + } + + return 0; +} + +/** + * ffa_probe() - The driver probe function + * @dev: the FF-A bus device (arm_ffa) + * + * Probing is triggered on demand by clients searching for the uclass. + * At probe level the following actions are done: + * - allocating private data (priv) with devres + * - updating priv with discovery information + * - 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 + * + * All data queried from secure world is saved in the private data structure (priv). + * + * Return: + * + * 0 on success. Otherwise, failure + */ +static int ffa_probe(struct udevice *dev) +{ + int ret; + struct ffa_priv *priv = NULL; + + ret = ffa_devm_alloc_priv(dev); + if (ret) + return ret; + + /* The data is dynamically allocated, managed by devres */ + priv = dev_get_priv(dev); + + priv->dscvry_info = dscvry_info; + + ret = ffa_get_endpoint_id(dev); + if (ret) + return ret; + + ret = ffa_get_rxtx_map_features(dev); + if (ret) + return ret; + + ret = ffa_map_rxtx_buffers(dev); + if (ret) + return ret; + + ret = ffa_cache_partitions_info(dev); + if (ret) { + ffa_unmap_rxtx_buffers(dev); + return ret; + } + + return 0; +} + +/** + * ffa_remove() - The driver remove function + * @dev: the arm_ffa device + * Making sure the RX/TX buffers are unmapped and freed when the device is removed. + * No need to free the private data structure because devres takes care of that. + * Return: + * + * 0 on success. + */ +static int ffa_remove(struct udevice *dev) +{ + log_info("[FFA] removing the device\n"); + + ffa_unmap_rxtx_buffers(dev); + dev_set_priv(dev, NULL); + + return 0; +} + +/** + * ffa_unbind() - The driver unbind function + * @dev: the arm_ffa device + * Making sure the RX/TX buffers are unmapped and freed when the device is unbound. + * No need to free the private data structure because devres takes care of that. + * Return: + * + * 0 on success. + */ +static int ffa_unbind(struct udevice *dev) +{ + struct ffa_priv *priv = dev_get_priv(dev); + + log_info("[FFA] unbinding the device\n"); + + if (priv) + ffa_unmap_rxtx_buffers(dev); + + return 0; +} + +/* FF-A driver operations */ + +static const struct ffa_bus_ops ffa_ops = { + .partition_info_get = ffa_get_partitions_info, + .sync_send_receive = ffa_msg_send_direct_req, + .rxtx_unmap = ffa_unmap_rxtx_buffers, +}; + +/* 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, + .probe = ffa_probe, + .remove = ffa_remove, + .unbind = ffa_unbind, + .ops = &ffa_ops, +}; diff --git a/include/arm_ffa.h b/include/arm_ffa.h new file mode 100644 index 0000000000..69f3c51080 --- /dev/null +++ b/include/arm_ffa.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi + */ + +#ifndef __ARM_FFA_H +#define __ARM_FFA_H + +#include + +/* + * 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_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 { + unsigned long data0; /* w3/x3 */ + unsigned long data1; /* w4/x4 */ + unsigned long data2; /* w5/x5 */ + unsigned long data3; /* w6/x6 */ + unsigned long data4; /* w7/x7 */ +}; + +struct udevice; + +/** + * struct ffa_bus_ops - The driver operations structure + * @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_info *buffer); + 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); +}; + +/* The device driver and the Uclass driver public functions */ + +/** + * ffa_bus_get_ops() - bus driver operations getter + * @dev: the arm_ffa device + * Returns a pointer to the FF-A driver ops field. + * Return: + * The ops pointer on success, NULL on failure. + */ +const struct ffa_bus_ops *ffa_bus_get_ops(struct udevice *dev); +#endif diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 33e43c20db..df77c7da58 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -4,6 +4,11 @@ * * (C) Copyright 2012 * Pavel Herrmann + * + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi */ #ifndef _DM_UCLASS_ID_H @@ -55,6 +60,7 @@ enum uclass_id { UCLASS_EFI_MEDIA, /* Devices provided by UEFI firmware */ UCLASS_ETH, /* Ethernet device */ UCLASS_ETH_PHY, /* Ethernet PHY device */ + UCLASS_FFA, /* Arm Firmware Framework for Armv8-A */ UCLASS_FIRMWARE, /* Firmware */ UCLASS_FPGA, /* FPGA device */ UCLASS_FUZZING_ENGINE, /* Fuzzing engine */ From patchwork Fri Mar 10 14:10:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdellatif El Khlifi X-Patchwork-Id: 1755241 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PY7Jr6PmQz1yWl for ; Sat, 11 Mar 2023 01:11:40 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 5CB2485F40; Fri, 10 Mar 2023 15:11:00 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id E7E7B85F1B; Fri, 10 Mar 2023 15:10:57 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id 78E6785F1B for ; Fri, 10 Mar 2023 15:10:46 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=abdellatif.elkhlifi@arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 495791515; Fri, 10 Mar 2023 06:11:28 -0800 (PST) Received: from e130802.arm.com (unknown [10.57.64.115]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 96A233F71A; Fri, 10 Mar 2023 06:10:42 -0800 (PST) From: Abdellatif El Khlifi To: sjg@chromium.org Cc: Drew.Reed@arm.com, abdellatif.elkhlifi@arm.com, achin.gupta@arm.com, ilias.apalodimas@linaro.org, jens.wiklander@linaro.org, nd@arm.com, robh@kernel.org, sudeep.holla@arm.com, trini@konsulko.com, u-boot@lists.denx.de, xueliang.zhong@arm.com Subject: [PATCH v9 05/10] arm_ffa: introduce armffa command Date: Fri, 10 Mar 2023 14:10:11 +0000 Message-Id: <20230310141016.137986-6-abdellatif.elkhlifi@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> References: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Provide armffa command showcasing the use of the FF-A driver armffa is a command showcasing how to use the FF-A driver and how to invoke its operations. This provides a guidance to the client developers on how to call the FF-A bus interfaces. The command also allows to gather secure partitions information and ping these partitions. The command is also helpful in testing the communication with secure partitions. For more details please refer to the command documentation [1]. [1]: doc/usage/cmd/armffa.rst Signed-off-by: Abdellatif El Khlifi Cc: Tom Rini Cc: Simon Glass Cc: Ilias Apalodimas Cc: Jens Wiklander --- Changelog: =============== v9: * remove manual FF-A discovery and use DM * use DM class APIs to probe and interact with the FF-A bus * add doc/usage/cmd/armffa.rst v8: * update partition_info_get() second argument to be an SP count * pass NULL device pointer to the FF-A bus discovery and operations v7: * adapt do_ffa_dev_list() following the recent update on uclass_first_device/uclass_next_device functions (they return void now) * set armffa command to use 64-bit direct messaging v4: * remove pattern data in do_ffa_msg_send_direct_req v3: * use the new driver interfaces (partition_info_get, sync_send_receive) in armffa command v2: * replace use of ffa_helper_init_device function by ffa_helper_bus_discover v1: * introduce armffa command MAINTAINERS | 2 + cmd/Kconfig | 10 ++ cmd/Makefile | 2 + cmd/armffa.c | 264 +++++++++++++++++++++++++++++++ doc/usage/cmd/armffa.rst | 118 ++++++++++++++ doc/usage/index.rst | 1 + drivers/firmware/arm-ffa/Kconfig | 1 + 7 files changed, 398 insertions(+) create mode 100644 cmd/armffa.c create mode 100644 doc/usage/cmd/armffa.rst diff --git a/MAINTAINERS b/MAINTAINERS index 1dfa23c1f0..18e9c2ce99 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -269,7 +269,9 @@ F: configs/cortina_presidio-asic-pnand_defconfig ARM FF-A M: Abdellatif El Khlifi S: Maintained +F: cmd/armffa.c F: doc/arch/arm64.ffa.rst +F: doc/usage/cmd/armffa.rst F: drivers/firmware/arm-ffa/ F: include/arm_ffa.h diff --git a/cmd/Kconfig b/cmd/Kconfig index a3512836c1..f24c52def4 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -934,6 +934,16 @@ endmenu menu "Device access commands" +config CMD_ARMFFA + bool "Arm FF-A test command" + depends on ARM_FFA_TRANSPORT + help + Provides a test command for the Arm FF-A driver + supported options: + - Listing the partition(s) info + - Sending a data pattern to the specified partition + - Displaying the arm_ffa device info + config CMD_ARMFLASH #depends on FLASH_CFI_DRIVER bool "armflash" diff --git a/cmd/Makefile b/cmd/Makefile index 2d8bb4fc05..a59ab55ad0 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -12,6 +12,8 @@ obj-y += panic.o obj-y += version.o # command + +obj-$(CONFIG_CMD_ARMFFA) += armffa.o obj-$(CONFIG_CMD_ACPI) += acpi.o obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o obj-$(CONFIG_CMD_AES) += aes.o diff --git a/cmd/armffa.c b/cmd/armffa.c new file mode 100644 index 0000000000..f6c017542d --- /dev/null +++ b/cmd/armffa.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi + */ + +#include +#include +#include +#include +#include +#include +#include + +/** + * do_ffa_getpart() - implementation of the getpart subcommand + * @cmdtp: Command Table + * @flag: flags + * @argc: number of arguments + * @argv: arguments + * + * This function queries the secure partition information which the UUID is provided + * as an argument. The function uses the arm_ffa driver partition_info_get operation + * which implements FFA_PARTITION_INFO_GET ABI to retrieve the data. + * The input UUID string is expected to be in big endian format. + * + * Return: + * + * CMD_RET_SUCCESS: on success, otherwise failure + */ +static int do_ffa_getpart(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + u32 count = 0; + int ret; + struct ffa_partition_info *parts_info; + u32 info_idx; + struct udevice *dev = NULL; + struct ffa_bus_ops *ffa_ops = NULL; + + if (argc != 1) + return -EINVAL; + + uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &dev); + if (!dev) { + log_err("[FFA] Cannot find FF-A bus device\n"); + return -ENODEV; + } + + ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(dev); + if (!ffa_ops) { + log_err("[FFA] Invalid FF-A ops\n"); + return -EINVAL; + } + + /* Mode 1: getting the number of secure partitions */ + ret = ffa_ops->partition_info_get(dev, argv[0], &count, NULL); + if (ret != 0) { + log_err("[FFA] Failure in querying partitions count (error code: %d)\n", ret); + return ret; + } + + if (!count) { + log_info("[FFA] No secure partition found\n"); + return ret; + } + + /* + * Pre-allocate a buffer to be filled by the driver + * with ffa_partition_info structs + */ + + log_info("[FFA] Pre-allocating %d partition(s) info structures\n", count); + + parts_info = calloc(count, sizeof(struct ffa_partition_info)); + if (!parts_info) + return -EINVAL; + + /* Ask the driver to fill the buffer with the SPs info */ + + ret = ffa_ops->partition_info_get(dev, argv[0], &count, parts_info); + if (ret != 0) { + log_err("[FFA] Failure in querying partition(s) info (error code: %d)\n", ret); + free(parts_info); + return ret; + } + + /* SPs found , show the partition information */ + for (info_idx = 0; info_idx < count ; info_idx++) { + log_info("[FFA] Partition: id = 0x%x , exec_ctxt 0x%x , properties 0x%x\n", + parts_info[info_idx].id, + parts_info[info_idx].exec_ctxt, + parts_info[info_idx].properties); + } + + free(parts_info); + + return 0; +} + +/** + * do_ffa_ping() - implementation of the ping subcommand + * @cmdtp: Command Table + * @flag: flags + * @argc: number of arguments + * @argv: arguments + * + * This function sends data to the secure partition which the ID is provided + * as an argument. The function uses the arm_ffa driver sync_send_receive operation + * which implements FFA_MSG_SEND_DIRECT_{REQ,RESP} ABIs to send/receive data. + * + * Return: + * + * CMD_RET_SUCCESS: on success, otherwise failure + */ +int do_ffa_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + struct ffa_send_direct_data msg = { + .data0 = 0xaaaaaaaa, + .data1 = 0xbbbbbbbb, + .data2 = 0xcccccccc, + .data3 = 0xdddddddd, + .data4 = 0xeeeeeeee, + }; + u16 part_id; + int ret; + struct udevice *dev = NULL; + struct ffa_bus_ops *ffa_ops = NULL; + + if (argc != 1) + return -EINVAL; + + errno = 0; + part_id = strtoul(argv[0], NULL, 16); + + if (errno) { + log_err("[FFA] Invalid partition ID\n"); + return -EINVAL; + } + + uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &dev); + if (!dev) { + log_err("[FFA] Cannot find FF-A bus device\n"); + return -ENODEV; + } + + ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(dev); + if (!ffa_ops) { + log_err("[FFA] Invalid FF-A ops\n"); + return -EINVAL; + } + + ret = ffa_ops->sync_send_receive(dev, part_id, &msg, 1); + if (!ret) { + u8 cnt; + + log_info("[FFA] SP response:\n[LSB]\n"); + for (cnt = 0; + cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); + cnt++) + log_info("[FFA] 0x%llx\n", ((u64 *)&msg)[cnt]); + } else { + log_err("[FFA] Sending direct request error (%d)\n", ret); + } + + return ret; +} + +/** + *do_ffa_devlist() - implementation of the devlist subcommand + * @cmdtp: [in] Command Table + * @flag: flags + * @argc: number of arguments + * @argv: arguments + * + * This function queries the devices belonging to the UCLASS_FFA + * class. + * + * Return: + * + * CMD_RET_SUCCESS: on success, otherwise failure + */ +int do_ffa_devlist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + struct udevice *dev = NULL; + int i; + + log_info("[FFA] FF-A uclass entries:\n"); + + for (i = 0, uclass_first_device(UCLASS_FFA, &dev); + dev; + uclass_next_device(&dev), i++) { + log_info("[FFA] entry %d - instance %08x, ops %08x, plat %08x\n", + i, + (u32)map_to_sysmem(dev), + (u32)map_to_sysmem(dev->driver->ops), + (u32)map_to_sysmem(dev_get_plat(dev))); + } + + return 0; +} + +static struct cmd_tbl armffa_commands[] = { + U_BOOT_CMD_MKENT(getpart, 1, 1, do_ffa_getpart, "", ""), + U_BOOT_CMD_MKENT(ping, 1, 1, do_ffa_ping, "", ""), + U_BOOT_CMD_MKENT(devlist, 0, 1, do_ffa_devlist, "", ""), +}; + +/** + * do_armffa() - the armffa command main function + * @cmdtp: Command Table + * @flag: flags + * @argc: number of arguments + * @argv: arguments + * + * This function identifies which armffa subcommand to run. + * Then, it makes sure the arm_ffa device is probed and + * ready for use. + * Then, it runs the subcommand. + * + * Return: + * + * CMD_RET_SUCCESS: on success, otherwise failure + */ +static int do_armffa(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + struct cmd_tbl *armffa_cmd; + int ret; + + if (argc < 2) + return CMD_RET_USAGE; + + armffa_cmd = find_cmd_tbl(argv[1], armffa_commands, ARRAY_SIZE(armffa_commands)); + + argc -= 2; + argv += 2; + + if (!armffa_cmd || argc > armffa_cmd->maxargs) + return CMD_RET_USAGE; + + if (IS_ENABLED(CONFIG_SANDBOX_FFA)) { + struct udevice *sdx_dev = NULL; + /* Probe the FF-A sandbox driver, then bind the FF-A bus driver */ + uclass_get_device_by_name(UCLASS_FFA, "sandbox_arm_ffa", &sdx_dev); + if (!sdx_dev) { + log_err("[FFA] Cannot find FF-A sandbox device\n"); + return -ENODEV; + } + } + + ret = armffa_cmd->cmd(armffa_cmd, flag, argc, argv); + + return cmd_process_error(armffa_cmd, ret); +} + +U_BOOT_CMD(armffa, 4, 1, do_armffa, + "Arm FF-A operations test command", + "getpart \n" + " - lists the partition(s) info\n" + "ping \n" + " - sends a data pattern to the specified partition\n" + "devlist\n" + " - displays instance info of FF-A devices (the bus and its associated sandbox\n"); diff --git a/doc/usage/cmd/armffa.rst b/doc/usage/cmd/armffa.rst new file mode 100644 index 0000000000..91f89971d1 --- /dev/null +++ b/doc/usage/cmd/armffa.rst @@ -0,0 +1,118 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +armffa command +============== + +Synopsis +-------- + +:: + + armffa [sub-command] [arguments] + + sub-commands: + + getpart [partition UUID] + + lists the partition(s) info + + ping [partition ID] + + sends a data pattern to the specified partition + + devlist + + displays instance info of FF-A devices (the bus and its associated sandbox) + +Description +----------- + +armffa is a command showcasing how to use the FF-A driver and how to invoke its operations. + +This provides a guidance to the client developers on how to call the FF-A bus interfaces. + +The command also allows to gather secure partitions information and ping these partitions. + +The command is also helpful in testing the communication with secure partitions. + +Example +------- + +The following examples are run on Corstone-1000 platform with debug logs enabled. + +* ping + +:: + + corstone1000# armffa ping 0x8003 + [FFA] endpoint ID is 0 + [FFA] Using 1 4KB page(s) for RX/TX buffers size + [FFA] RX buffer at virtual address 00000000fdf48000 + [FFA] TX buffer at virtual address 00000000fdf4a000 + [FFA] RX/TX buffers mapped + [FFA] Reading partitions data from the RX buffer + [FFA] Partition ID 8001 : info cached + [FFA] Partition ID 8002 : info cached + [FFA] Partition ID 8003 : info cached + [FFA] 3 partition(s) found and cached + [FFA] SP response: + [LSB] + [FFA] 0xfffffffe + [FFA] 0x0 + [FFA] 0x0 + [FFA] 0x0 + [FFA] 0x0 + +* ping (failure case) + +:: + + corstone1000# armffa ping 0x1234 + [FFA] Sending direct request error (-22) + Command 'ping' failed: Error -22 + +* getpart + +:: + + corstone1000# armffa getpart 33d532ed-e699-0942-c09c-a798d9cd722d + [FFA] Preparing for checking partitions count + [FFA] Searching partitions using the provided UUID + [FFA] No partition found. Querying framework ... + [FFA] Reading partitions data from the RX buffer + [FFA] Number of partition(s) matching the UUID: 1 + [FFA] Pre-allocating 1 partition(s) info structures + [FFA] Preparing for filling partitions info + [FFA] Searching partitions using the provided UUID + [FFA] Partition ID 8003 matches the provided UUID + [FFA] Partition: id = 0x8003 , exec_ctxt 0x1 , properties 0x3 + +* getpart (failure case) + +:: + + corstone1000# armffa getpart ed32d533-4209-99e6-2d72-cdd998a79cc0 + [FFA] Preparing for checking partitions count + [FFA] Searching partitions using the provided UUID + [FFA] No partition found. Querying framework ... + [FFA] INVALID_PARAMETERS: Unrecognized UUID + [FFA] Failure in querying partitions count (error code: -22) + Command 'getpart' failed: Error -22 + +* devlist + +:: + + corstone1000# armffa devlist + [FFA] FF-A uclass entries: + [FFA] entry 0 - instance fdf40c50, ops fffc0408, plat 00000000 + +Configuration +------------- + +The command is available if CONFIG_CMD_ARMFFA=y and CONFIG_ARM_FFA_TRANSPORT=y. + +Return value +------------ + +The return value $? is 0 (true) on success and a negative error code on failure. diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 840c20c934..f1b9335cb1 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -21,6 +21,7 @@ Shell commands cmd/acpi cmd/addrmap + cmd/armffa cmd/askenv cmd/base cmd/bdinfo diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig index e5b2912201..2cfd7ef5fc 100644 --- a/drivers/firmware/arm-ffa/Kconfig +++ b/drivers/firmware/arm-ffa/Kconfig @@ -5,6 +5,7 @@ config ARM_FFA_TRANSPORT depends on DM && ARM64 select ARM_SMCCC select ARM_SMCCC_FEATURES + imply CMD_ARMFFA select LIB_UUID select DEVRES help From patchwork Fri Mar 10 14:10:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdellatif El Khlifi X-Patchwork-Id: 1755242 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PY7K561tYz1yWl for ; Sat, 11 Mar 2023 01:11:53 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 661EA85F22; Fri, 10 Mar 2023 15:11:15 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id F11C485F2A; Fri, 10 Mar 2023 15:11:10 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id 5553285A98 for ; Fri, 10 Mar 2023 15:10:48 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=abdellatif.elkhlifi@arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 34D39C14; Fri, 10 Mar 2023 06:11:31 -0800 (PST) Received: from e130802.arm.com (unknown [10.57.64.115]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 127A33F71A; Fri, 10 Mar 2023 06:10:44 -0800 (PST) From: Abdellatif El Khlifi To: sjg@chromium.org Cc: Drew.Reed@arm.com, abdellatif.elkhlifi@arm.com, achin.gupta@arm.com, ilias.apalodimas@linaro.org, jens.wiklander@linaro.org, nd@arm.com, robh@kernel.org, sudeep.holla@arm.com, trini@konsulko.com, u-boot@lists.denx.de, xueliang.zhong@arm.com Subject: [PATCH v9 06/10] arm_ffa: introduce the FF-A Sandbox driver Date: Fri, 10 Mar 2023 14:10:12 +0000 Message-Id: <20230310141016.137986-7-abdellatif.elkhlifi@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> References: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Provide a Sandbox driver to emulate the FF-A ABIs The emulated ABIs are those supported by the FF-A core driver and according to FF-A specification v1.0. The Sandbox driver provides operations allowing the test application to read the status of all the inspected ABIs and perform functional tests based on that. sandbox driver supports only 64-bit direct messaging. Signed-off-by: Abdellatif El Khlifi Cc: Tom Rini Cc: Simon Glass Cc: Ilias Apalodimas Cc: Jens Wiklander --- Changelog: =============== v9: align FF-A sandbox driver with FF-A discovery through DM v8: update ffa_bus_prvdata_get() to return a pointer rather than a pointer address v7: state that sandbox driver supports only 64-bit direct messaging v4: align sandbox driver with the new FF-A driver interfaces and new way of error handling v1: introduce the sandbox driver MAINTAINERS | 1 + arch/sandbox/dts/sandbox.dtsi | 4 + arch/sandbox/dts/test.dts | 4 + configs/sandbox64_defconfig | 2 + configs/sandbox_defconfig | 2 + doc/arch/arm64.ffa.rst | 4 + doc/arch/sandbox/sandbox.rst | 1 + drivers/firmware/arm-ffa/Kconfig | 11 +- drivers/firmware/arm-ffa/Makefile | 1 + drivers/firmware/arm-ffa/core.c | 36 +- drivers/firmware/arm-ffa/sandbox.c | 610 ++++++++++++++++++ .../firmware/arm-ffa/sandbox_arm_ffa_priv.h | 129 ++++ include/arm_ffa.h | 5 +- include/sandbox_arm_ffa.h | 124 ++++ 14 files changed, 928 insertions(+), 6 deletions(-) create mode 100644 drivers/firmware/arm-ffa/sandbox.c create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h create mode 100644 include/sandbox_arm_ffa.h diff --git a/MAINTAINERS b/MAINTAINERS index 18e9c2ce99..2b9d33e964 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -274,6 +274,7 @@ F: doc/arch/arm64.ffa.rst F: doc/usage/cmd/armffa.rst F: drivers/firmware/arm-ffa/ F: include/arm_ffa.h +F: include/sandbox_arm_ffa.h ARM FREESCALE IMX M: Stefano Babic diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index 30a305c4d2..059c273277 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -445,6 +445,10 @@ thermal { compatible = "sandbox,thermal"; }; + + sandbox_arm_ffa { + compatible = "sandbox,arm_ffa"; + }; }; &cros_ec { diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index d72d7a567a..11dc6ed0d9 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -1802,6 +1802,10 @@ compatible = "u-boot,fwu-mdata-gpt"; fwu-mdata-store = <&mmc0>; }; + + sandbox_arm_ffa { + compatible = "sandbox,arm_ffa"; + }; }; #include "sandbox_pmic.dtsi" diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index ccbc18aad0..35d4676cf7 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -259,3 +259,5 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +CONFIG_ARM_FFA_TRANSPORT=y +CONFIG_SANDBOX_FFA=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index a0fbdad20a..8aab8dda31 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -336,3 +336,5 @@ CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +CONFIG_ARM_FFA_TRANSPORT=y +CONFIG_SANDBOX_FFA=y \ No newline at end of file diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst index 8fad9ef3d0..555ee9a6ae 100644 --- a/doc/arch/arm64.ffa.rst +++ b/doc/arch/arm64.ffa.rst @@ -64,6 +64,10 @@ CONFIG_ARM_FFA_TRANSPORT Enables the FF-A bus driver. Turn this on if you want to use FF-A communication. +CONFIG_SANDBOX_FFA + Enables FF-A Sandbox driver. This emulates the FF-A ABIs handling under + Sandbox and provides functional tests for FF-A. + FF-A ABIs under the hood --------------------------------------- diff --git a/doc/arch/sandbox/sandbox.rst b/doc/arch/sandbox/sandbox.rst index cd7f8a2cb0..c5df372e00 100644 --- a/doc/arch/sandbox/sandbox.rst +++ b/doc/arch/sandbox/sandbox.rst @@ -200,6 +200,7 @@ Supported Drivers U-Boot sandbox supports these emulations: +- Arm FF-A - Block devices - Chrome OS EC - GPIO diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig index 2cfd7ef5fc..b5430eb6f4 100644 --- a/drivers/firmware/arm-ffa/Kconfig +++ b/drivers/firmware/arm-ffa/Kconfig @@ -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 imply CMD_ARMFFA select LIB_UUID select DEVRES @@ -32,3 +32,8 @@ config ARM_FFA_TRANSPORT For more details about the FF-A driver, please refer to doc/arch/arm64.ffa.rst +config SANDBOX_FFA + bool "FF-A Sandbox driver" + depends on ARM_FFA_TRANSPORT && SANDBOX + help + This emulates the FF-A handling under Sandbox and allows to test the FF-A driver diff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile index c8d83b4bc9..d22c1ba609 100644 --- a/drivers/firmware/arm-ffa/Makefile +++ b/drivers/firmware/arm-ffa/Makefile @@ -6,3 +6,4 @@ # Abdellatif El Khlifi obj-y += arm-ffa-uclass.o core.o +obj-$(CONFIG_SANDBOX_FFA) += sandbox.o diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c index 2210f5343c..0d2e6ff0d4 100644 --- a/drivers/firmware/arm-ffa/core.c +++ b/drivers/firmware/arm-ffa/core.c @@ -1042,6 +1042,7 @@ bool ffa_try_discovery(void) return true; } +#if !CONFIG_IS_ENABLED(SANDBOX_FFA) /** * __arm_ffa_fn_smc() - SMC wrapper * @args: FF-A ABI arguments to be copied to Xn registers @@ -1069,6 +1070,7 @@ void __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res) * The FF-A driver supports the SMCCCv1.2 extended input/output registers. * So, the legacy SMC invocation is not used. * + * In Sandbox mode sandbox_arm_ffa is used to test arm_ffa driver. * Return: * * 0 on success. Otherwise, failure @@ -1088,6 +1090,30 @@ ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = { .driver_name = FFA_DRV_NAME, .is_supported = ffa_bus_is_supported, }; +#else +/* SANDBOX_FFA */ + +/** + * ffa_bind() - The driver bind function + * @dev: the arm_ffa device + * When using sandbox tries to discover the emulated FF-A bus. + * Return: + * + * 0 on success. + */ +static int ffa_bind(struct udevice *dev) +{ + bool ret; + + log_info("[FFA] binding the device\n"); + + ret = ffa_try_discovery(); + if (ret) + return 0; + else + return -ENODEV; +} +#endif /** * ffa_set_smc_conduit() - Set the SMC conduit @@ -1101,7 +1127,12 @@ ARM_SMCCC_FEATURE_DRIVER(arm_ffa) = { */ static int ffa_set_smc_conduit(void) { - dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc; +#if CONFIG_IS_ENABLED(SANDBOX_FFA) + dscvry_info.invoke_ffa_fn = sandbox_arm_ffa_smccc_smc; + log_info("[FFA] Using SMC emulation\n"); +#else + dscvry_info.invoke_ffa_fn = __arm_ffa_fn_smc; +#endif log_info("[FFA] Conduit is SMC\n"); @@ -1246,4 +1277,7 @@ U_BOOT_DRIVER(arm_ffa) = { .remove = ffa_remove, .unbind = ffa_unbind, .ops = &ffa_ops, +#if CONFIG_IS_ENABLED(SANDBOX_FFA) + .bind = ffa_bind, +#endif }; diff --git a/drivers/firmware/arm-ffa/sandbox.c b/drivers/firmware/arm-ffa/sandbox.c new file mode 100644 index 0000000000..84c2fc929f --- /dev/null +++ b/drivers/firmware/arm-ffa/sandbox.c @@ -0,0 +1,610 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sandbox_arm_ffa_priv.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_SP2_ID, .exec_ctxt = 0x9587, .properties = 0x45325621 }, + .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_SP3_ID, .exec_ctxt = 0x7687, .properties = 0x23325621 }, + .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, + } + } + +}; + +/* Driver functions */ + +/** + * sandbox_ffa_version() - Emulated FFA_VERSION handler function + * @dev: the sandbox FF-A device + * @{a0-a7} , res: The SMC call arguments and return structure. + * + * This is the function that emulates FFA_VERSION FF-A function. + * + * Return: + * + * 0 on success. Otherwise, failure + */ +SANDBOX_SMC_FFA_ABI(ffa_version) +{ + struct sandbox_ffa_priv *priv = dev_get_priv(dev); + + 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(unsigned long)); + + return 0; +} + +/** + * sandbox_ffa_id_get() - Emulated FFA_ID_GET handler function + * @dev: the sandbox FF-A device + * @{a0-a7} , res: The SMC call arguments and return structure. + * + * This is the function that emulates FFA_ID_GET FF-A function. + * + * Return: + * + * 0 on success. Otherwise, failure + */ +SANDBOX_SMC_FFA_ABI(ffa_id_get) +{ + struct sandbox_ffa_priv *priv = dev_get_priv(dev); + + 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(unsigned long)); + + return 0; +} + +/** + * sandbox_ffa_features() - Emulated FFA_FEATURES handler function + * @dev: the sandbox FF-A device + * @{a0-a7} , res: The SMC call arguments and return structure. + * + * This is the function that emulates FFA_FEATURES FF-A function. + * + * Return: + * + * 0 on success. Otherwise, failure + */ +SANDBOX_SMC_FFA_ABI(ffa_features) +{ + 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(unsigned long)); + } else { + res->a0 = FFA_SMC_32(FFA_ERROR); + res->a2 = FFA_ERR_STAT_NOT_SUPPORTED; + /* x3-x7 MBZ */ + memset(FFA_X3_MBZ_REG_START, + 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long)); + log_err("[FFA] [Sandbox] FF-A interface 0x%lx not implemented\n", pargs->a1); + } + + res->a1 = 0; + + return 0; +} + +/** + * sandbox_ffa_partition_info_get() - Emulated FFA_PARTITION_INFO_GET handler function + * @dev: the sandbox FF-A device + * @{a0-a7} , res: The SMC call arguments and return structure. + * + * This is the function that emulates FFA_PARTITION_INFO_GET FF-A function. + * + * Return: + * + * 0 on success. Otherwise, failure + */ +SANDBOX_SMC_FFA_ABI(ffa_partition_info_get) +{ + struct ffa_partition_info *rxbuf_desc_info = NULL; + u32 descs_cnt; + u32 descs_size_bytes; + struct sandbox_ffa_priv *priv = dev_get_priv(dev); + + res->a0 = FFA_SMC_32(FFA_ERROR); + + if (!priv->pair.rxbuf) { + res->a2 = FFA_ERR_STAT_DENIED; + goto cleanup; + } + + if (priv->pair_info.rxbuf_owned) { + res->a2 = FFA_ERR_STAT_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 descriptors buffer size */ + if ((priv->pair_info.rxtx_buf_size * SZ_4K) < descs_size_bytes) { + res->a2 = FFA_ERR_STAT_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; + + goto cleanup; + } + + /* A UUID is specified. Return the information of all partitions 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 = (unsigned long) + (rxbuf_desc_info - (struct ffa_partition_info *)priv->pair.rxbuf); + + /* Transfer ownership to the consumer: the non secure world */ + priv->pair_info.rxbuf_owned = 1; + } else { + /* Unrecognized UUID */ + res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS; + } + +cleanup: + + log_err("[FFA] [Sandbox] 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(unsigned long)); + + return 0; +} + +/** + * sandbox_ffa_rxtx_map() - Emulated FFA_RXTX_MAP handler function + * @dev: the sandbox FF-A device + * @{a0-a7} , res: The SMC call arguments and return structure. + * + * This is the function that emulates FFA_RXTX_MAP FF-A function. + * + * Return: + * + * 0 on success. Otherwise, failure + */ +SANDBOX_SMC_FFA_ABI(ffa_rxtx_map) +{ + struct sandbox_ffa_priv *priv = dev_get_priv(dev); + + res->a0 = FFA_SMC_32(FFA_ERROR); + + if (priv->pair.txbuf && priv->pair.rxbuf) { + res->a2 = FFA_ERR_STAT_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; + goto feedback; + } + + if (!pargs->a1 || !pargs->a2) + res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS; + else + res->a2 = FFA_ERR_STAT_NO_MEMORY; + + log_err("[FFA] [Sandbox] 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(unsigned long)); + + return 0; +} + +/** + * sandbox_ffa_rxtx_unmap() - Emulated FFA_RXTX_UNMAP handler function + * @dev: the sandbox FF-A device + * @{a0-a7} , res: The SMC call arguments and return structure. + * + * This is the function that emulates FFA_RXTX_UNMAP FF-A function. + * + * Return: + * + * 0 on success. Otherwise, failure + */ +SANDBOX_SMC_FFA_ABI(ffa_rxtx_unmap) +{ + struct sandbox_ffa_priv *priv = dev_get_priv(dev); + + res->a0 = FFA_SMC_32(FFA_ERROR); + res->a2 = FFA_ERR_STAT_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; + goto feedback; + } + + log_err("[FFA] [Sandbox] 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(unsigned long)); + + return 0; +} + +/** + * sandbox_ffa_rx_release() - Emulated FFA_RX_RELEASE handler function + * @dev: the sandbox FF-A device + * @{a0-a7} , res: The SMC call arguments and return structure. + * + * This is the function that emulates FFA_RX_RELEASE FF-A function. + * + * Return: + * + * 0 on success. Otherwise, failure + */ +SANDBOX_SMC_FFA_ABI(ffa_rx_release) +{ + struct sandbox_ffa_priv *priv = dev_get_priv(dev); + + if (!priv->pair_info.rxbuf_owned) { + res->a0 = FFA_SMC_32(FFA_ERROR); + res->a2 = FFA_ERR_STAT_DENIED; + } else { + priv->pair_info.rxbuf_owned = 0; + res->a0 = FFA_SMC_32(FFA_SUCCESS); + res->a2 = 0; + } + + res->a1 = 0; + + /* x3-x7 MBZ */ + memset(FFA_X3_MBZ_REG_START, + 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long)); + + return 0; +} + +/** + * sandbox_ffa_sp_valid() - Checks SP validity + * @dev: the sandbox_arm_ffa device + * @part_id: partition ID to check + * + * This is the function searches the input ID in the descriptors table. + * + * Return: + * + * 1 on success (Partition found). Otherwise, failure + */ +static int sandbox_ffa_sp_valid(struct udevice *dev, u16 part_id) +{ + u32 descs_cnt; + struct sandbox_ffa_priv *priv = dev_get_priv(dev); + + 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 function + * @dev: the sandbox FF-A device + * @{a0-a7} , res: The SMC call arguments and return structure. + * + * This is the function that emulates FFA_MSG_SEND_DIRECT_{REQ,RESP} + * FF-A functions. 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 + */ +SANDBOX_SMC_FFA_ABI(ffa_msg_send_direct_req) +{ + u16 part_id; + struct sandbox_ffa_priv *priv = dev_get_priv(dev); + + part_id = GET_DST_SP_ID(pargs->a1); + + if ((GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id) || + !sandbox_ffa_sp_valid(dev, part_id) || pargs->a2) { + res->a0 = FFA_SMC_32(FFA_ERROR); + res->a1 = 0; + res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS; + + /* x3-x7 MBZ */ + memset(FFA_X3_MBZ_REG_START, + 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long)); + + return 0; + } + + 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 = 0xffffffffffffffff; + res->a4 = 0xffffffffffffffff; + res->a5 = 0xffffffffffffffff; + res->a6 = 0xffffffffffffffff; + res->a7 = 0xffffffffffffffff; + + return 0; +} + +/** + * sandbox_ffa_get_rxbuf_flags() - Reading the mapping/ownership flags + * @dev: the sandbox_arm_ffa device + * @queried_func_id: The FF-A function to be queried + * @func_data: Pointer to the FF-A function arguments container structure + * + * This is the handler that queries 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 *dev, u32 queried_func_id, + struct ffa_sandbox_data *func_data) +{ + struct sandbox_ffa_priv *priv = dev_get_priv(dev); + + 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("[FFA] [Sandbox] The querried FF-A interface flag (%d) undefined\n", + queried_func_id); + return -EINVAL; + } +} + +/** + * sandbox_ffa_query_core_state() - The driver dispatcher function + * @dev: the sandbox_arm_ffa device + * @queried_func_id: The FF-A function to be queried + * @func_data: Pointer to the FF-A function arguments container structure + * + * Queries the status of FF-A ABI specified in the input argument. + * + * Return: + * + * 0 on success. Otherwise, failure + */ +int sandbox_ffa_query_core_state(struct udevice *dev, u32 queried_func_id, + struct ffa_sandbox_data *func_data) +{ + switch (queried_func_id) { + case FFA_RXTX_MAP: + case FFA_RXTX_UNMAP: + case FFA_RX_RELEASE: + return sandbox_ffa_get_rxbuf_flags(dev, queried_func_id, func_data); + default: + log_err("[FFA] [Sandbox] 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 + * + * Sandbox driver emulates the FF-A ABIs SMC call using this function. + * 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 *dev = NULL; + + uclass_get_device_by_name(UCLASS_FFA, "sandbox_arm_ffa", &dev); + if (!dev) { + log_err("[FFA] [Sandbox] Cannot find FF-A sandbox device\n"); + return; + } + + switch (args.a0) { + case FFA_SMC_32(FFA_VERSION): + ret = sandbox_ffa_version(dev, &args, res); + break; + case FFA_SMC_32(FFA_PARTITION_INFO_GET): + ret = sandbox_ffa_partition_info_get(dev, &args, res); + break; + case FFA_SMC_32(FFA_RXTX_UNMAP): + ret = sandbox_ffa_rxtx_unmap(dev, &args, res); + break; + case FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ): + ret = sandbox_ffa_msg_send_direct_req(dev, &args, res); + break; + case FFA_SMC_32(FFA_ID_GET): + ret = sandbox_ffa_id_get(dev, &args, res); + break; + case FFA_SMC_32(FFA_FEATURES): + ret = sandbox_ffa_features(dev, &args, res); + break; + case FFA_SMC_64(FFA_RXTX_MAP): + ret = sandbox_ffa_rxtx_map(dev, &args, res); + break; + case FFA_SMC_32(FFA_RX_RELEASE): + ret = sandbox_ffa_rx_release(dev, &args, res); + break; + default: + log_err("[FFA] [Sandbox] Undefined FF-A interface (0x%lx)\n", args.a0); + } + + if (ret != 0) + log_err("[FFA] [Sandbox] FF-A ABI internal failure (%d)\n", ret); +} + +/** + * sandbox_ffa_probe() - The driver probe function + * @dev: the sandbox_arm_ffa device + * + * Binds the FF-A bus driver and sets the sandbox device as the FF-A bus device parent + * + * Return: + * + * 0 on success. Otherwise, failure + */ +static int sandbox_ffa_probe(struct udevice *dev) +{ + struct udevice *child_dev = NULL; + int ret; + + ret = device_bind_driver(dev, FFA_DRV_NAME, FFA_DRV_NAME, &child_dev); + if (ret) { + pr_err("%s was not bound: %d, aborting\n", FFA_DRV_NAME, ret); + return -ENODEV; + } + + dev_set_parent_plat(child_dev, dev_get_plat(dev)); + + return 0; +} + +static const struct udevice_id sandbox_ffa_id[] = { + { "sandbox,arm_ffa", 0 }, + { }, +}; + +/* Declaring the sandbox_arm_ffa driver under UCLASS_FFA */ +U_BOOT_DRIVER(sandbox_arm_ffa) = { + .name = FFA_SANDBOX_DRV_NAME, + .of_match = sandbox_ffa_id, + .id = UCLASS_FFA, + .probe = sandbox_ffa_probe, + .priv_auto = sizeof(struct sandbox_ffa_priv), +}; diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h new file mode 100644 index 0000000000..c35d80de16 --- /dev/null +++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi + */ + +#ifndef __SANDBOX_ARM_FFA_PRV_H +#define __SANDBOX_ARM_FFA_PRV_H + +#include +#include "arm_ffa_priv.h" + +/* This header is exclusively used by the Sandbox FF-A driver and sandbox tests */ + +/* FF-A core driver name */ +#define FFA_SANDBOX_DRV_NAME "sandbox_arm_ffa" + +/* FF-A ABIs internal error codes (as defined by the spec) */ + +#define FFA_ERR_STAT_NOT_SUPPORTED -1 +#define FFA_ERR_STAT_INVALID_PARAMETERS -2 +#define FFA_ERR_STAT_NO_MEMORY -3 +#define FFA_ERR_STAT_BUSY -4 +#define FFA_ERR_STAT_DENIED -6 + +/* 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 secure partitions emulated by the FF-A sandbox driver */ +#define SANDBOX_PARTITIONS_CNT (4) + +/* Binary data of services UUIDs emulated by the FF-A sandbox driver */ + +/* 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: the consumer) + * @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 as set by the FF-A core driver + * + * Data structure hosting 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_priv - the driver private data structure + * + * @dev: The arm_ffa device under u-boot driver model + * @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 + * @conduit: The selected conduit + * + * The driver data structure hosting all the emulated secure world data. + */ +struct sandbox_ffa_priv { + struct udevice *dev; + u32 fwk_version; + u16 id; + struct ffa_partitions partitions; + struct ffa_rxtxpair pair; + struct ffa_rxtxpair_info pair_info; +}; + +#define SANDBOX_SMC_FFA_ABI(ffabi) static int sandbox_##ffabi(struct udevice *dev, \ + ffa_value_t *pargs, ffa_value_t *res) + +#endif diff --git a/include/arm_ffa.h b/include/arm_ffa.h index 69f3c51080..70a9eefae6 100644 --- a/include/arm_ffa.h +++ b/include/arm_ffa.h @@ -12,8 +12,9 @@ #include /* - * This header is public. It can be used by clients to access - * data structures and definitions they need + * This header is used to access FF-A data structures + * and definitions. The header is used by the FF-A core driver, clients, + * sandbox driver, sandbox tests, armffa command */ /* diff --git a/include/sandbox_arm_ffa.h b/include/sandbox_arm_ffa.h new file mode 100644 index 0000000000..3d99b6b8fa --- /dev/null +++ b/include/sandbox_arm_ffa.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi + */ + +#ifndef __SANDBOX_ARM_FFA_H +#define __SANDBOX_ARM_FFA_H + +#include + +/* + * This header provides the sandbox driver declarations + * needed by FF-A driver, armffa command and sandbox tests + */ + +/* Providing Arm SMCCC declarations to sandbox */ + +#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)) + +/** + * struct sandbox_smccc_1_2_regs - Arguments for or Results from emulated SMC call + * @a0-a17 argument values from registers 0 to 17 + */ +struct sandbox_smccc_1_2_regs { + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; + unsigned long a4; + unsigned long a5; + unsigned long a6; + unsigned long a7; + unsigned long a8; + unsigned long a9; + unsigned long a10; + unsigned long a11; + unsigned long a12; + unsigned long a13; + unsigned long a14; + unsigned long a15; + unsigned long a16; + unsigned long a17; +}; + +typedef struct sandbox_smccc_1_2_regs ffa_value_t; + +/* UUIDs strings of services emulated by the FF-A sandbox driver */ +#define SANDBOX_SERVICE1_UUID "ed32d533-4209-99e6-2d72-cdd998a79cc0" +#define SANDBOX_SERVICE2_UUID "ed32d544-4209-99e6-2d72-cdd998a79cc0" + +/* IDs of secure partitions (SPs) emulated by the FF-A sandbox driver */ +#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 - generic data structure used to exchange + * data between test cases and the sandbox driver + * @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 + * + * Using this structure sandbox test cases can pass various types of data with different sizes. + */ +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 driver public functions */ + +/** + * sandbox_ffa_query_core_state() - The driver dispatcher function + * @dev: the sandbox_arm_ffa device + * @queried_func_id: The FF-A function to be queried + * @func_data: Pointer to the FF-A function arguments container structure + * Return: + * 0 on success. Otherwise, failure + */ +int sandbox_ffa_query_core_state(struct udevice *dev, u32 queried_func_id, + struct ffa_sandbox_data *func_data); + +/** + * sandbox_arm_ffa_smccc_smc() - FF-A SMC call emulation + * @args: the SMC call arguments + * @res: the SMC call returned data + * 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); + +#endif From patchwork Fri Mar 10 14:10:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdellatif El Khlifi X-Patchwork-Id: 1755243 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PY7KL4ZvWz1yWl for ; Sat, 11 Mar 2023 01:12:06 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 1D83185B2A; Fri, 10 Mar 2023 15:11:21 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id 1362685A98; Fri, 10 Mar 2023 15:11:12 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id AB66285F29 for ; Fri, 10 Mar 2023 15:10:51 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=abdellatif.elkhlifi@arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 45CF11515; Fri, 10 Mar 2023 06:11:34 -0800 (PST) Received: from e130802.arm.com (unknown [10.57.64.115]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 0AA733F71A; Fri, 10 Mar 2023 06:10:47 -0800 (PST) From: Abdellatif El Khlifi To: sjg@chromium.org Cc: Drew.Reed@arm.com, abdellatif.elkhlifi@arm.com, achin.gupta@arm.com, ilias.apalodimas@linaro.org, jens.wiklander@linaro.org, nd@arm.com, robh@kernel.org, sudeep.holla@arm.com, trini@konsulko.com, u-boot@lists.denx.de, xueliang.zhong@arm.com Subject: [PATCH v9 07/10] arm_ffa: introduce Sandbox test cases for UCLASS_FFA Date: Fri, 10 Mar 2023 14:10:13 +0000 Message-Id: <20230310141016.137986-8-abdellatif.elkhlifi@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> References: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Add functional test cases for the FF-A core driver These tests rely on the FF-A Sandbox driver which helps in inspecting the FF-A core driver. Signed-off-by: Abdellatif El Khlifi Cc: Tom Rini Cc: Simon Glass Cc: Ilias Apalodimas Cc: Jens Wiklander --- Changelog: =============== v9: align FF-A sandbox tests with FF-A discovery through DM v8: * update partition_info_get() second argument to be an SP count * pass NULL device pointer to the FF-A bus discovery and operations v7: set the tests to use 64-bit direct messaging v4: align sandbox tests with the new FF-A driver interfaces and new way of error handling v1: introduce sandbox tests MAINTAINERS | 1 + test/dm/Makefile | 2 + test/dm/ffa.c | 380 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 383 insertions(+) create mode 100644 test/dm/ffa.c diff --git a/MAINTAINERS b/MAINTAINERS index 2b9d33e964..6939b832e4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -275,6 +275,7 @@ F: doc/usage/cmd/armffa.rst F: drivers/firmware/arm-ffa/ F: include/arm_ffa.h F: include/sandbox_arm_ffa.h +F: test/dm/ffa.c ARM FREESCALE IMX M: Stefano Babic diff --git a/test/dm/Makefile b/test/dm/Makefile index 7a79b6e1a2..b554b170db 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0+ # # Copyright (c) 2013 Google, Inc +# Copyright 2022-2023 Arm Limited and/or its affiliates obj-$(CONFIG_UT_DM) += test-dm.o @@ -85,6 +86,7 @@ obj-$(CONFIG_POWER_DOMAIN) += power-domain.o obj-$(CONFIG_ACPI_PMC) += pmc.o obj-$(CONFIG_DM_PMIC) += pmic.o obj-$(CONFIG_DM_PWM) += pwm.o +obj-$(CONFIG_SANDBOX_FFA) += ffa.o obj-$(CONFIG_QFW) += qfw.o obj-$(CONFIG_RAM) += ram.o obj-y += regmap.o diff --git a/test/dm/ffa.c b/test/dm/ffa.c new file mode 100644 index 0000000000..d978feda72 --- /dev/null +++ b/test/dm/ffa.c @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Functional tests for UCLASS_FFA class + * + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi + */ + +#include +#include +#include +#include +#include "../../drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h" +#include +#include +#include + +/* Macros */ + +#define LOG_MSG_SZ (100) +#define LOG_CMD_SZ (LOG_MSG_SZ * 2) + +/* Functional tests for the UCLASS_FFA */ + +static int dm_test_ffa_log(struct unit_test_state *uts, char *msg) +{ + char cmd[LOG_CMD_SZ] = {0}; + + console_record_reset(); + + snprintf(cmd, LOG_CMD_SZ, "echo \"%s\"", msg); + run_command(cmd, 0); + + ut_assert_console_end(); + + return 0; +} + +static int check_fwk_version(struct ffa_priv *priv, struct sandbox_ffa_priv *sdx_priv, + struct unit_test_state *uts) +{ + if (priv->dscvry_info.fwk_version != sdx_priv->fwk_version) { + char msg[LOG_MSG_SZ] = {0}; + + snprintf(msg, LOG_MSG_SZ, + "[%s]: Error: framework version: core = 0x%x , sandbox = 0x%x", __func__, + priv->dscvry_info.fwk_version, + sdx_priv->fwk_version); + + dm_test_ffa_log(uts, msg); + return CMD_RET_FAILURE; + } + return 0; +} + +static int check_endpoint_id(struct ffa_priv *priv, struct unit_test_state *uts) +{ + if (priv->id) { + char msg[LOG_MSG_SZ] = {0}; + + snprintf(msg, LOG_MSG_SZ, + "[%s]: Error: endpoint id: core = 0x%x", __func__, priv->id); + dm_test_ffa_log(uts, msg); + return CMD_RET_FAILURE; + } + return 0; +} + +static int check_rxtxbuf(struct ffa_priv *priv, struct unit_test_state *uts) +{ + if (!priv->pair.rxbuf && priv->pair.txbuf) { + char msg[LOG_MSG_SZ] = {0}; + + snprintf(msg, LOG_MSG_SZ, "[%s]: Error: rxbuf = %p txbuf = %p", __func__, + priv->pair.rxbuf, + priv->pair.txbuf); + dm_test_ffa_log(uts, msg); + return CMD_RET_FAILURE; + } + return 0; +} + +static int check_features(struct ffa_priv *priv, struct unit_test_state *uts) +{ + char msg[LOG_MSG_SZ] = {0}; + + if (priv->pair.rxtx_min_pages != RXTX_4K && + priv->pair.rxtx_min_pages != RXTX_16K && + priv->pair.rxtx_min_pages != RXTX_64K) { + snprintf(msg, + LOG_MSG_SZ, + "[%s]: Error: FFA_RXTX_MAP features = 0x%lx", + __func__, + priv->pair.rxtx_min_pages); + dm_test_ffa_log(uts, msg); + return CMD_RET_FAILURE; + } + + return 0; +} + +static int check_rxbuf_mapped_flag(u32 queried_func_id, + u8 rxbuf_mapped, + struct unit_test_state *uts) +{ + char msg[LOG_MSG_SZ] = {0}; + + switch (queried_func_id) { + case FFA_RXTX_MAP: + { + if (rxbuf_mapped) + return 0; + break; + } + case FFA_RXTX_UNMAP: + { + if (!rxbuf_mapped) + return 0; + break; + } + default: + return CMD_RET_FAILURE; + } + + snprintf(msg, LOG_MSG_SZ, "[%s]: Error: %s mapping issue", __func__, + (queried_func_id == FFA_RXTX_MAP ? "FFA_RXTX_MAP" : "FFA_RXTX_UNMAP")); + dm_test_ffa_log(uts, msg); + + return CMD_RET_FAILURE; +} + +static int check_rxbuf_release_flag(u8 rxbuf_owned, struct unit_test_state *uts) +{ + if (rxbuf_owned) { + char msg[LOG_MSG_SZ] = {0}; + + snprintf(msg, LOG_MSG_SZ, "[%s]: Error: RX buffer not released", __func__); + dm_test_ffa_log(uts, msg); + return CMD_RET_FAILURE; + } + return 0; +} + +static int test_ffa_msg_send_direct_req(u16 part_id, struct unit_test_state *uts) +{ + struct ffa_send_direct_data msg = {0}; + u8 cnt; + struct udevice *ffa_dev = NULL; + struct ffa_bus_ops *ffa_ops = NULL; + + uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev); + ut_assertok(!ffa_dev); + + ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev); + ut_assertok(!ffa_ops); + + ut_assertok(ffa_ops->sync_send_receive(ffa_dev, part_id, &msg, 1)); + + for (cnt = 0; cnt < sizeof(struct ffa_send_direct_data) / sizeof(u64); cnt++) + ut_assertok(((u64 *)&msg)[cnt] != 0xffffffffffffffff); + + return 0; +} + +static int test_partitions_and_comms(const char *service_uuid, + struct sandbox_ffa_priv *sdx_priv, + struct unit_test_state *uts) +{ + u32 count = 0; + struct ffa_partition_info *parts_info; + u32 info_idx, exp_info_idx; + int ret; + struct udevice *ffa_dev = NULL; + struct ffa_bus_ops *ffa_ops = NULL; + + uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev); + ut_assertok(!ffa_dev); + + ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev); + ut_assertok(!ffa_ops); + + /* Get from the driver the count of the SPs matching the UUID */ + ret = ffa_ops->partition_info_get(ffa_dev, service_uuid, &count, NULL); + /* Make sure partitions are detected */ + ut_assertok(ret != 0); + ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE); + + /* Pre-allocate a buffer to be filled by the driver with ffa_partition_info structs */ + + parts_info = calloc(count, sizeof(struct ffa_partition_info)); + ut_assertok(!parts_info); + + /* Ask the driver to fill the buffer with the SPs info */ + ret = ffa_ops->partition_info_get(ffa_dev, service_uuid, &count, parts_info); + if (ret != 0) { + free(parts_info); + ut_assertok(ret != 0); + } + + /* SPs found , verify the partitions information */ + + ret = CMD_RET_FAILURE; + + for (info_idx = 0; info_idx < count ; info_idx++) { + for (exp_info_idx = 0; + exp_info_idx < sdx_priv->partitions.count; + exp_info_idx++) { + if (parts_info[info_idx].id == + sdx_priv->partitions.descs[exp_info_idx].info.id) { + ret = memcmp(&parts_info[info_idx], + &sdx_priv->partitions.descs[exp_info_idx] + .info, + sizeof(struct ffa_partition_info)); + if (ret) + free(parts_info); + ut_assertok(ret != 0); + /* Send and receive data from the current partition */ + test_ffa_msg_send_direct_req(parts_info[info_idx].id, uts); + } + ret = 0; + } + } + + free(parts_info); + + /* Verify expected partitions found in the emulated secure world */ + ut_assertok(ret != 0); + + return 0; +} + +static int dm_test_ffa_ack(struct unit_test_state *uts) +{ + struct ffa_priv *priv = NULL; + struct sandbox_ffa_priv *sdx_priv = NULL; + struct ffa_sandbox_data func_data = {0}; + u8 rxbuf_flag = 0; + const char *svc1_uuid = SANDBOX_SERVICE1_UUID; + const char *svc2_uuid = SANDBOX_SERVICE2_UUID; + int ret; + struct udevice *ffa_dev = NULL, *sdx_dev = NULL; + struct ffa_bus_ops *ffa_ops = NULL; + + /* Test probing the FF-A sandbox driver, then binding the FF-A bus driver */ + uclass_get_device_by_name(UCLASS_FFA, "sandbox_arm_ffa", &sdx_dev); + ut_assertok(!sdx_dev); + + /* Test probing the FF-A bus driver */ + uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev); + ut_assertok(!ffa_dev); + + ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev); + ut_assertok(!ffa_ops); + + /* Get a pointer to the FF-A core and sandbox drivers private data */ + priv = dev_get_priv(ffa_dev); + sdx_priv = dev_get_priv(sdx_dev); + + /* Make sure private data pointers are retrieved */ + ut_assertok(priv == 0); + ut_assertok(sdx_priv == 0); + + /* Test FFA_VERSION */ + ut_assertok(check_fwk_version(priv, sdx_priv, uts)); + + /* Test FFA_ID_GET */ + ut_assertok(check_endpoint_id(priv, uts)); + + /* Test FFA_FEATURES */ + ut_assertok(check_features(priv, uts)); + + /* Test core RX/TX buffers */ + ut_assertok(check_rxtxbuf(priv, uts)); + + /* Test FFA_RXTX_MAP */ + func_data.data0 = &rxbuf_flag; + func_data.data0_size = sizeof(rxbuf_flag); + + rxbuf_flag = 0; + ut_assertok(sandbox_ffa_query_core_state(sdx_dev, FFA_RXTX_MAP, &func_data)); + ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_MAP, rxbuf_flag, uts)); + + /* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */ + ret = test_partitions_and_comms(svc1_uuid, sdx_priv, uts); + ut_assertok(ret != 0); + + /* Test FFA_RX_RELEASE */ + rxbuf_flag = 1; + ut_assertok(sandbox_ffa_query_core_state(sdx_dev, FFA_RX_RELEASE, &func_data)); + ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts)); + + /* FFA_PARTITION_INFO_GET / FFA_MSG_SEND_DIRECT_REQ */ + ret = test_partitions_and_comms(svc2_uuid, sdx_priv, uts); + ut_assertok(ret != 0); + + /* Test FFA_RX_RELEASE */ + rxbuf_flag = 1; + ut_assertok(sandbox_ffa_query_core_state(sdx_dev, FFA_RX_RELEASE, &func_data)); + ut_assertok(check_rxbuf_release_flag(rxbuf_flag, uts)); + + /* Test FFA_RXTX_UNMAP */ + ut_assertok(ffa_ops->rxtx_unmap(ffa_dev)); + + rxbuf_flag = 1; + ut_assertok(sandbox_ffa_query_core_state(sdx_dev, FFA_RXTX_UNMAP, &func_data)); + ut_assertok(check_rxbuf_mapped_flag(FFA_RXTX_UNMAP, rxbuf_flag, uts)); + + return 0; +} + +DM_TEST(dm_test_ffa_ack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); + +static int dm_test_ffa_nack(struct unit_test_state *uts) +{ + struct ffa_priv *priv = NULL; + struct sandbox_ffa_priv *sdx_priv = NULL; + const char *valid_svc_uuid = SANDBOX_SERVICE1_UUID; + const char *unvalid_svc_uuid = SANDBOX_SERVICE3_UUID; + const char *unvalid_svc_uuid_str = SANDBOX_SERVICE4_UUID; + struct ffa_send_direct_data msg = {0}; + int ret; + u32 count = 0; + u16 part_id = 0; + struct udevice *ffa_dev = NULL, *sdx_dev = NULL; + struct ffa_bus_ops *ffa_ops = NULL; + + /* Test probing the FF-A sandbox driver, then binding the FF-A bus driver */ + uclass_get_device_by_name(UCLASS_FFA, "sandbox_arm_ffa", &sdx_dev); + ut_assertok(!sdx_dev); + + /* Test probing the FF-A bus driver */ + uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev); + ut_assertok(!ffa_dev); + + ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev); + ut_assertok(!ffa_ops); + + /* Get a pointer to the FF-A core and sandbox drivers private data */ + priv = dev_get_priv(ffa_dev); + sdx_priv = dev_get_priv(sdx_dev); + + /* Make sure private data pointers are retrieved */ + ut_assertok(priv == 0); + ut_assertok(sdx_priv == 0); + + /* Query partitions count using invalid arguments */ + ret = ffa_ops->partition_info_get(ffa_dev, unvalid_svc_uuid, NULL, NULL); + ut_assertok(ret != -EINVAL); + + /* Query partitions count using an invalid UUID string */ + ret = ffa_ops->partition_info_get(ffa_dev, unvalid_svc_uuid_str, &count, NULL); + ut_assertok(ret != -EINVAL); + + /* Query partitions count using an invalid UUID (no matching SP) */ + count = 0; + ret = ffa_ops->partition_info_get(ffa_dev, unvalid_svc_uuid, &count, NULL); + ut_assertok(count != 0); + + /* Query partitions count using a valid UUID */ + count = 0; + ret = ffa_ops->partition_info_get(ffa_dev, valid_svc_uuid, &count, NULL); + /* Make sure partitions are detected */ + ut_assertok(ret != 0); + ut_assertok(count != SANDBOX_SP_COUNT_PER_VALID_SERVICE); + + /* Send data to an invalid partition */ + ret = ffa_ops->sync_send_receive(ffa_dev, part_id, &msg, 1); + ut_assertok(ret != -EINVAL); + + /* Send data to a valid partition */ + part_id = priv->partitions.descs[0].info.id; + ret = ffa_ops->sync_send_receive(ffa_dev, part_id, &msg, 1); + ut_assertok(ret != 0); + + return 0; +} + +DM_TEST(dm_test_ffa_nack, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); From patchwork Fri Mar 10 14:10:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdellatif El Khlifi X-Patchwork-Id: 1755245 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PY7Kr4RP0z1yWl for ; Sat, 11 Mar 2023 01:12:32 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id CC9D385F3E; Fri, 10 Mar 2023 15:11:27 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id E4EBC85D95; Fri, 10 Mar 2023 15:11:13 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id CF15885F39 for ; Fri, 10 Mar 2023 15:10:55 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=abdellatif.elkhlifi@arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B52DFC14; Fri, 10 Mar 2023 06:11:38 -0800 (PST) Received: from e130802.arm.com (unknown [10.57.64.115]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 51B9D3F71A; Fri, 10 Mar 2023 06:10:50 -0800 (PST) From: Abdellatif El Khlifi To: sjg@chromium.org Cc: Drew.Reed@arm.com, abdellatif.elkhlifi@arm.com, achin.gupta@arm.com, ilias.apalodimas@linaro.org, jens.wiklander@linaro.org, nd@arm.com, robh@kernel.org, sudeep.holla@arm.com, trini@konsulko.com, u-boot@lists.denx.de, xueliang.zhong@arm.com Subject: [PATCH v9 08/10] arm_ffa: introduce armffa command Sandbox test Date: Fri, 10 Mar 2023 14:10:14 +0000 Message-Id: <20230310141016.137986-9-abdellatif.elkhlifi@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> References: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Add Sandbox test for the armffa command Signed-off-by: Abdellatif El Khlifi Cc: Tom Rini Cc: Simon Glass Cc: Ilias Apalodimas Cc: Jens Wiklander Reviewed-by: Simon Glass --- Changelog: =============== v9: align the test with FF-A discovery through DM v4: drop use of helper APIs v1: introduce armffa command sandbox test MAINTAINERS | 1 + test/cmd/Makefile | 2 ++ test/cmd/armffa.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 test/cmd/armffa.c diff --git a/MAINTAINERS b/MAINTAINERS index 6939b832e4..b36fb41668 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -275,6 +275,7 @@ F: doc/usage/cmd/armffa.rst F: drivers/firmware/arm-ffa/ F: include/arm_ffa.h F: include/sandbox_arm_ffa.h +F: test/cmd/armffa.c F: test/dm/ffa.c ARM FREESCALE IMX diff --git a/test/cmd/Makefile b/test/cmd/Makefile index 2ffde8703a..e74da56a29 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0+ # # Copyright (c) 2013 Google, Inc +# Copyright 2022-2023 Arm Limited and/or its affiliates ifdef CONFIG_HUSH_PARSER obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o @@ -19,6 +20,7 @@ obj-$(CONFIG_CMD_PWM) += pwm.o obj-$(CONFIG_CMD_SEAMA) += seama.o ifdef CONFIG_SANDBOX obj-$(CONFIG_CMD_SETEXPR) += setexpr.o +obj-$(CONFIG_SANDBOX_FFA) += armffa.o endif obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o obj-$(CONFIG_CMD_WGET) += wget.o diff --git a/test/cmd/armffa.c b/test/cmd/armffa.c new file mode 100644 index 0000000000..73c895f182 --- /dev/null +++ b/test/cmd/armffa.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for armffa command + * + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi + */ + +#include +#include +#include +#include +#include +#include + +#define PING_CMD_SIZE 19 + +/* Basic test of 'armffa' command */ +static int dm_test_armffa_cmd(struct unit_test_state *uts) +{ + char ping_cmd[PING_CMD_SIZE] = {0}; + + /* armffa getpart */ + ut_assertok(run_command("armffa getpart " SANDBOX_SERVICE1_UUID, 0)); + + snprintf(ping_cmd, PING_CMD_SIZE, "armffa ping 0x%x", SANDBOX_SP1_ID); + + /* armffa ping */ + ut_assertok(run_command(ping_cmd, 0)); + + /* armffa devlist */ + ut_assertok(run_command("armffa devlist", 0)); + + return CMD_RET_SUCCESS; +} + +DM_TEST(dm_test_armffa_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC); From patchwork Fri Mar 10 14:10:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdellatif El Khlifi X-Patchwork-Id: 1755247 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PY7LL6VBQz1yWl for ; Sat, 11 Mar 2023 01:12:58 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6DF4585D8D; Fri, 10 Mar 2023 15:11:39 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id E681A85D88; Fri, 10 Mar 2023 15:11:22 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id 3473185F3F for ; Fri, 10 Mar 2023 15:10:59 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=abdellatif.elkhlifi@arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 1E1F5C14; Fri, 10 Mar 2023 06:11:42 -0800 (PST) Received: from e130802.arm.com (unknown [10.57.64.115]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 981CB3F71A; Fri, 10 Mar 2023 06:10:55 -0800 (PST) From: Abdellatif El Khlifi To: sjg@chromium.org Cc: Drew.Reed@arm.com, abdellatif.elkhlifi@arm.com, achin.gupta@arm.com, ilias.apalodimas@linaro.org, jens.wiklander@linaro.org, nd@arm.com, robh@kernel.org, sudeep.holla@arm.com, trini@konsulko.com, u-boot@lists.denx.de, xueliang.zhong@arm.com, Gowtham Suresh Kumar Subject: [PATCH v9 09/10] arm_ffa: efi: introduce FF-A MM communication Date: Fri, 10 Mar 2023 14:10:15 +0000 Message-Id: <20230310141016.137986-10-abdellatif.elkhlifi@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> References: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Add MM communication support using FF-A transport This feature allows accessing MM partitions services through EFI MM communication protocol. MM partitions such as StandAlonneMM or smm-gateway secure partitions which reside in secure world. An MM shared buffer and a door bell event are used to exchange the data. The data is used by EFI services such as GetVariable()/SetVariable() and copied from the communication buffer to the MM shared buffer. The secure partition is notified about availability of data in the MM shared buffer by an FF-A message (door bell). On such event, MM SP can read the data and updates the MM shared buffer with the response data. The response data is copied back to the communication buffer and consumed by the EFI subsystem. MM communication protocol supports FF-A 64-bit direct messaging. Signed-off-by: Abdellatif El Khlifi Signed-off-by: Gowtham Suresh Kumar Cc: Tom Rini Cc: Simon Glass Cc: Ilias Apalodimas Cc: Jens Wiklander --- Changelog: =============== v9: align how FF-A is used with FF-A discovery through DM v8: * isolate the compilation choices between FF-A and OP-TEE * update partition_info_get() second argument to be an SP count * pass NULL device pointer to the FF-A bus discovery and operations v7: * set the MM door bell event to use 64-bit direct messaging * issue a compile time error when one of these macros are not found : FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_OFFSET, FFA_SHARED_MM_BUFFER_ADDR * make mm_sp_svc_uuid static * replace EINVAL with ENOMEM in ffa_discover_mm_sp_id() when calloc() fails * improve use of unmap_sysmem() in ffa_mm_communicate() v6: * add FF-A runtime discovery at MM communication level * drop EFI runtime support for FF-A MM communication * revert the changes in include/mm_communication.h for efi_mm_communicate_header and smm_variable_access structures v4: * use the new FF-A driver interfaces * discover MM partitions at runtime * copy FF-A driver private data to EFI runtime section at ExitBootServices() * drop use of FFA_ERR_STAT_SUCCESS error code * replace EFI_BUFFER_TOO_SMALL with EFI_OUT_OF_RESOURCES in ffa_mm_communicate(). No need for efi_memcpy_runtime() anymore * revert the error log in mm_communicate() in case of failure * remove packed attribute from efi_mm_communicate_header and smm_variable_communicate_header v2: * set default values to 0 for FFA_SHARED_MM_BUFFER_SIZE, FFA_SHARED_MM_BUFFER_ADDR and MM_SP_UUID_DATA and add warnings v1: * introduce FF-A MM communication include/mm_communication.h | 6 + lib/efi_loader/Kconfig | 14 +- lib/efi_loader/efi_variable_tee.c | 317 +++++++++++++++++++++++++++++- 3 files changed, 331 insertions(+), 6 deletions(-) diff --git a/include/mm_communication.h b/include/mm_communication.h index e65fbde60d..87509fec3f 100644 --- a/include/mm_communication.h +++ b/include/mm_communication.h @@ -6,6 +6,9 @@ * Copyright (c) 2017, Intel Corporation. All rights reserved. * Copyright (C) 2020 Linaro Ltd. * Copyright (C) 2020 Linaro Ltd. + * Copyright 2022-2023 Arm Limited and/or its affiliates + * Authors: + * Abdellatif El Khlifi */ #ifndef _MM_COMMUNICATION_H_ @@ -13,6 +16,9 @@ #include +/* MM service UUID string (big-endian format). This UUID is common across all MM SPs */ +#define MM_SP_UUID "33d532ed-e699-0942-c09c-a798d9cd722d" + /* * Interface to the pseudo Trusted Application (TA), which provides a * communication channel with the Standalone MM (Management Mode) diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index c5835e6ef6..08a6b84101 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE stored as file /ubootefi.var on the EFI system partition. config EFI_MM_COMM_TEE - bool "UEFI variables storage service via OP-TEE" - depends on OPTEE + bool "UEFI variables storage service via the trusted world" + depends on OPTEE || ARM_FFA_TRANSPORT help + Allowing access to the MM SP services (SPs such as StandAlonneMM, smm-gateway). + When using the u-boot OP-TEE driver, StandAlonneMM is supported. + When using the u-boot FF-A driver any MM SP is supported. + If OP-TEE is present and running StandAloneMM, dispatch all UEFI variable related operations to that. The application will verify, authenticate and store the variables on an RPMB. + When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related + operations to the MM SP running in the secure world. + A door bell mechanism is used to notify the SP when there is data in the shared + MM buffer. The data is copied by u-boot to the shared buffer before issuing + the door bell event. + config EFI_VARIABLE_NO_STORE bool "Don't persist non-volatile UEFI variables" help diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c index dfef18435d..86207f1ff2 100644 --- a/lib/efi_loader/efi_variable_tee.c +++ b/lib/efi_loader/efi_variable_tee.c @@ -4,9 +4,14 @@ * * Copyright (C) 2019 Linaro Ltd. * Copyright (C) 2019 Linaro Ltd. + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi */ #include +#include #include #include #include @@ -15,6 +20,36 @@ #include #include +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) + +#include +#include +#include + +#ifndef FFA_SHARED_MM_BUFFER_SIZE +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/.h" +#define FFA_SHARED_MM_BUFFER_SIZE 0 +#endif + +#ifndef FFA_SHARED_MM_BUFFER_OFFSET +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/.h" +#define FFA_SHARED_MM_BUFFER_OFFSET 0 +#endif + +#ifndef FFA_SHARED_MM_BUFFER_ADDR +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/.h" +#define FFA_SHARED_MM_BUFFER_ADDR 0 +#endif + +/* MM return codes */ +#define MM_SUCCESS (0) + +static const char *mm_sp_svc_uuid = MM_SP_UUID; + +static u16 mm_sp_id; + +#endif + extern struct efi_var_file __efi_runtime_data *efi_var_buf; static efi_uintn_t max_buffer_size; /* comm + var + func + data */ static efi_uintn_t max_payload_size; /* func + data */ @@ -24,6 +59,7 @@ struct mm_connection { u32 session; }; +#if (IS_ENABLED(CONFIG_OPTEE)) /** * get_connection() - Retrieve OP-TEE session for a specific UUID. * @@ -143,13 +179,269 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize) return ret; } +#endif + +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) + +/** + * ffa_notify_mm_sp() - Announce there is data in the shared buffer + * + * Notifies the MM partition in the trusted world that + * data is available in the shared buffer. + * This is a blocking call during which trusted world has exclusive access + * to the MM shared buffer. + * + * Return: + * + * 0 on success + */ +static int ffa_notify_mm_sp(void) +{ + struct ffa_send_direct_data msg = {0}; + int ret; + int sp_event_ret = -1; + struct udevice *ffa_dev = NULL; + struct ffa_bus_ops *ffa_ops = NULL; + + uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev); + if (!ffa_dev) { + log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n"); + return -ENODEV; + } + + ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev); + if (!ffa_ops) { + log_err("EFI: Invalid FF-A ops, notify MM SP failure\n"); + return -EINVAL; + } + + msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */ + + ret = ffa_ops->sync_send_receive(ffa_dev, mm_sp_id, &msg, 1); + if (ret != 0) + return ret; + + sp_event_ret = msg.data0; /* x3 */ + + if (sp_event_ret == MM_SUCCESS) + return 0; + + /* + * Failure to notify the MM SP + */ + + return -EACCES; +} + +/** + * ffa_discover_mm_sp_id() - Query the MM partition ID + * + * Use the FF-A driver to get the MM partition ID. + * If multiple partitions are found, use the first one. + * This is a boot time function. + * + * Return: + * + * 0 on success + */ +static int ffa_discover_mm_sp_id(void) +{ + u32 count = 0; + int ret; + struct ffa_partition_info *parts_info; + struct udevice *ffa_dev = NULL; + struct ffa_bus_ops *ffa_ops = NULL; + + uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &ffa_dev); + if (!ffa_dev) { + log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n"); + return -ENODEV; + } + + ffa_ops = (struct ffa_bus_ops *)ffa_bus_get_ops(ffa_dev); + if (!ffa_ops) { + log_err("EFI: Invalid FF-A ops, MM SP discovery failure\n"); + return -EINVAL; + } + + /* Get from the driver the count of the SPs matching the UUID */ + ret = ffa_ops->partition_info_get(ffa_dev, mm_sp_svc_uuid, &count, NULL); + if (ret != 0) { + log_err("EFI: Failure in querying SPs count (%d), MM SP discovery failure\n", ret); + return ret; + } + + if (!count) { + log_info("EFI: No MM partition found\n"); + return ret; + } + + /* Pre-allocate a buffer to be filled by the driver with ffa_partition_info structs */ + + log_info("EFI: Pre-allocating %d partition(s) info structures\n", count); + + parts_info = calloc(count, sizeof(*parts_info)); + if (!parts_info) + return -ENOMEM; + + /* Ask the driver to fill the buffer with the SPs info */ + ret = ffa_ops->partition_info_get(ffa_dev, mm_sp_svc_uuid, &count, parts_info); + if (ret) { + log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret); + free(parts_info); + return ret; + } + + /* MM SPs found , use the first one */ + + mm_sp_id = parts_info[0].id; + + log_info("EFI: MM partition ID 0x%x\n", mm_sp_id); + + free(parts_info); + + return 0; +} + +/** + * ffa_mm_communicate() - Exchange EFI services data with the MM partition using FF-A + * @comm_buf: locally allocated communication buffer used for rx/tx + * @dsize: communication buffer size + * + * Issues a door bell event to notify the MM partition (SP) running in OP-TEE + * that there is data to read from the shared buffer. + * Communication with the MM SP is performed using FF-A transport. + * On the event, MM SP can read the data from the buffer and + * update the MM shared buffer with response data. + * The response data is copied back to the communication buffer. + * + * Return: + * + * EFI status code + */ +static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size) +{ + ulong tx_data_size; + int ffa_ret; + efi_status_t efi_ret; + struct efi_mm_communicate_header *mm_hdr; + void *virt_shared_buf; + + if (!comm_buf) + return EFI_INVALID_PARAMETER; + + /* Discover MM partition ID at boot time */ + if (!mm_sp_id && ffa_discover_mm_sp_id() != 0) { + log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n"); + return EFI_UNSUPPORTED; + } + + mm_hdr = (struct efi_mm_communicate_header *)comm_buf; + tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t); + + if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE) + return EFI_INVALID_PARAMETER; + + /* Copy the data to the shared buffer */ + + virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0); + memcpy(virt_shared_buf, comm_buf, tx_data_size); + + /* + * The secure world might have cache disabled for + * the device region used for shared buffer (which is the case for Optee). + * In this case, the secure world reads the data from DRAM. + * Let's flush the cache so the DRAM is updated with the latest data. + */ + #ifdef CONFIG_ARM64 + invalidate_dcache_all(); + #endif + + /* Announce there is data in the shared buffer */ + + ffa_ret = ffa_notify_mm_sp(); + + switch (ffa_ret) { + case 0: + { + ulong rx_data_size; + /* Copy the MM SP response from the shared buffer to the communication buffer */ + rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len + + sizeof(efi_guid_t) + + sizeof(size_t); + + if (rx_data_size > comm_buf_size) { + efi_ret = EFI_OUT_OF_RESOURCES; + break; + } + + memcpy(comm_buf, virt_shared_buf, rx_data_size); + efi_ret = EFI_SUCCESS; + break; + } + case -EINVAL: + efi_ret = EFI_DEVICE_ERROR; + break; + case -EPERM: + efi_ret = EFI_INVALID_PARAMETER; + break; + case -EACCES: + efi_ret = EFI_ACCESS_DENIED; + break; + case -EBUSY: + efi_ret = EFI_OUT_OF_RESOURCES; + break; + default: + efi_ret = EFI_ACCESS_DENIED; + } + + unmap_sysmem(virt_shared_buf); + return efi_ret; +} +#endif + +/** + * select_ffa_mm_comms() - checks FF-A support availability + * + * Making sure FF-A is compiled in. If that's the case try to make sure + * the FF-A bus is probed successfully which means FF-A communication + * with secure world works and ready to be used. + * + * Return: + * + * 0: FF-A ready for use. Otherwise, failure + */ +static efi_status_t select_ffa_mm_comms(void) +{ + efi_status_t ret = EFI_UNSUPPORTED; + + if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) { + struct udevice *dev = NULL; + + uclass_get_device_by_name(UCLASS_FFA, "arm_ffa", &dev); + if (!dev) { + log_err("EFI: Cannot find FF-A bus device, cannot select FF-A comms\n"); + ret = EFI_NOT_READY; + } else { + ret = EFI_SUCCESS; + } + } + + return ret; +} /** - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send + * mm_communicate() - Adjust the communication buffer to the MM SP and send * it to OP-TEE * - * @comm_buf: locally allocted communcation buffer + * @comm_buf: locally allocated communication buffer * @dsize: buffer size + * + * The SP (also called partition) can be any MM SP such as StandAlonneMM or smm-gateway. + * The comm_buf format is the same for both partitions. + * When using the u-boot OP-TEE driver, StandAlonneMM is supported. + * When using the u-boot FF-A driver, any MM SP is supported. + * * Return: status code */ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize) @@ -162,7 +454,17 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize) mm_hdr = (struct efi_mm_communicate_header *)comm_buf; var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data; - ret = optee_mm_communicate(comm_buf, dsize); + ret = select_ffa_mm_comms(); + if (ret != EFI_SUCCESS) { +#if (IS_ENABLED(CONFIG_OPTEE)) + ret = optee_mm_communicate(comm_buf, dsize); +#endif + } else { +#if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) + ret = ffa_mm_communicate(comm_buf, dsize); +#endif + } + if (ret != EFI_SUCCESS) { log_err("%s failed!\n", __func__); return ret; @@ -258,6 +560,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size) goto out; } *size = var_payload->size; + + #if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) + if (*size > FFA_SHARED_MM_BUFFER_SIZE) + *size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE - + MM_VARIABLE_COMMUNICATE_SIZE; + #endif + /* * There seems to be a bug in EDK2 miscalculating the boundaries and * size checks, so deduct 2 more bytes to fulfill this requirement. Fix @@ -697,7 +1006,7 @@ void efi_variables_boot_exit_notify(void) ret = EFI_NOT_FOUND; if (ret != EFI_SUCCESS) - log_err("Unable to notify StMM for ExitBootServices\n"); + log_err("Unable to notify the MM partition for ExitBootServices\n"); free(comm_buf); /* From patchwork Fri Mar 10 14:10:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdellatif El Khlifi X-Patchwork-Id: 1755246 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PY7L62qzbz1yWl for ; Sat, 11 Mar 2023 01:12:46 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 0205485D91; Fri, 10 Mar 2023 15:11:32 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id AE84885F28; Fri, 10 Mar 2023 15:11:19 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id 5C51685F43 for ; Fri, 10 Mar 2023 15:11:02 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=abdellatif.elkhlifi@arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id E7C2DC14; Fri, 10 Mar 2023 06:11:44 -0800 (PST) Received: from e130802.arm.com (unknown [10.57.64.115]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D12843F71A; Fri, 10 Mar 2023 06:10:58 -0800 (PST) From: Abdellatif El Khlifi To: sjg@chromium.org Cc: Drew.Reed@arm.com, abdellatif.elkhlifi@arm.com, achin.gupta@arm.com, ilias.apalodimas@linaro.org, jens.wiklander@linaro.org, nd@arm.com, robh@kernel.org, sudeep.holla@arm.com, trini@konsulko.com, u-boot@lists.denx.de, xueliang.zhong@arm.com Subject: [PATCH v9 10/10] arm_ffa: efi: corstone1000: enable MM communication Date: Fri, 10 Mar 2023 14:10:16 +0000 Message-Id: <20230310141016.137986-11-abdellatif.elkhlifi@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> References: <20230310141016.137986-1-abdellatif.elkhlifi@arm.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean turn on EFI MM communication On corstone1000 platform MM communication between u-boot and the secure world (Optee) is done using the FF-A bus. Signed-off-by: Abdellatif El Khlifi Cc: Tom Rini Cc: Simon Glass Cc: Ilias Apalodimas Cc: Jens Wiklander --- Changelog: =============== v9: update copyright string v8: * drop OP-TEE configs from Corstone-1000 defconfig v7: * improve the definition of FFA_SHARED_MM_BUFFER_ADDR and FFA_SHARED_MM_BUFFER_OFFSET * update FFA_SHARED_MM_BUFFER_ADDR value v6: * corstone-1000: enable optee driver * corstone-1000: remove CONFIG_ARM_FFA_EFI_RUNTIME_MODE from the defconfig v4: * corstone-1000: turn on EFI MM communication configs/corstone1000_defconfig | 2 ++ include/configs/corstone1000.h | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig index 74250c7524..a7bfcbb2b9 100644 --- a/configs/corstone1000_defconfig +++ b/configs/corstone1000_defconfig @@ -52,3 +52,5 @@ CONFIG_DM_SERIAL=y CONFIG_USB=y CONFIG_USB_ISP1760=y CONFIG_ERRNO_STR=y +CONFIG_EFI_MM_COMM_TEE=y +CONFIG_ARM_FFA_TRANSPORT=y diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h index 3347c11792..4ef1f05e40 100644 --- a/include/configs/corstone1000.h +++ b/include/configs/corstone1000.h @@ -1,9 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * (C) Copyright 2022 ARM Limited * (C) Copyright 2022 Linaro * Rui Miguel Silva - * Abdellatif El Khlifi + * Copyright 2022-2023 Arm Limited and/or its affiliates + * + * Authors: + * Abdellatif El Khlifi * * Configuration for Corstone1000. Parts were derived from other ARM * configurations. @@ -14,6 +16,15 @@ #include +#define FFA_SHARED_MM_BUFFER_SIZE SZ_4K /* 4 KB */ + +/* + * shared buffer physical address used for communication between + * u-boot and the MM SP + */ +#define FFA_SHARED_MM_BUFFER_ADDR 0x02000000UL +#define FFA_SHARED_MM_BUFFER_OFFSET 0 + #define V2M_BASE 0x80000000 #define CFG_PL011_CLOCK 50000000