From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 01FF3C32771 for ; Mon, 26 Sep 2022 10:20:57 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 5D8C884DD3; Mon, 26 Sep 2022 12:20:21 +0200 (CEST) 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 4D24F84DA5; Mon, 26 Sep 2022 12:19:24 +0200 (CEST) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id 6345084DA8 for ; Mon, 26 Sep 2022 12:18:00 +0200 (CEST) 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 4E5131063; Mon, 26 Sep 2022 03:18:06 -0700 (PDT) Received: from e121910.arm.com (unknown [10.57.32.60]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 742483F73B; Mon, 26 Sep 2022 03:17:57 -0700 (PDT) From: Abdellatif El Khlifi To: abdellatif.elkhlifi@arm.com Cc: u-boot@lists.denx.de, ilias.apalodimas@linaro.org, jens.wiklander@linaro.org, trini@konsulko.com, sjg@chromium.org, vishnu.banavath@arm.com, xueliang.zhong@arm.com, achin.gupta@arm.com, nd@arm.com Subject: [PATCH v4 06/10] arm_ffa: introduce the FF-A Sandbox driver Date: Mon, 26 Sep 2022 11:17:19 +0100 Message-Id: <20220926101723.9965-7-abdellatif.elkhlifi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220926101723.9965-1-abdellatif.elkhlifi@arm.com> References: <20220801172053.20163-1-abdellatif.elkhlifi@arm.com> <20220926101723.9965-1-abdellatif.elkhlifi@arm.com> 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.6 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. Signed-off-by: Abdellatif El Khlifi Cc: Tom Rini Cc: Simon Glass Cc: Ilias Apalodimas Cc: Jens Wiklander Changelog: =============== v4: align sandbox driver with the new FF-A driver interfaces and new way of error handling v1: introduce the sandbox driver --- MAINTAINERS | 1 + common/board_r.c | 2 +- configs/sandbox64_defconfig | 2 + configs/sandbox_defconfig | 2 + doc/arch/sandbox.rst | 1 + drivers/firmware/arm-ffa/Kconfig | 10 +- drivers/firmware/arm-ffa/Makefile | 1 + drivers/firmware/arm-ffa/arm_ffa_prv.h | 15 +- drivers/firmware/arm-ffa/core.c | 24 +- drivers/firmware/arm-ffa/sandbox.c | 659 ++++++++++++++++++ .../firmware/arm-ffa/sandbox_arm_ffa_prv.h | 144 ++++ include/arm_ffa.h | 2 +- include/sandbox_arm_ffa.h | 91 +++ lib/efi_loader/efi_boottime.c | 2 +- 14 files changed, 941 insertions(+), 15 deletions(-) create mode 100644 drivers/firmware/arm-ffa/sandbox.c create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h create mode 100644 include/sandbox_arm_ffa.h diff --git a/MAINTAINERS b/MAINTAINERS index fd3b2c4263..6f01002e34 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -255,6 +255,7 @@ F: cmd/armffa.c F: doc/README.ffa.drv 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/common/board_r.c b/common/board_r.c index 8c99faddfd..7f1eae65df 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -776,7 +776,7 @@ static init_fnc_t init_sequence_r[] = { INIT_FUNC_WATCHDOG_RESET initr_net, #endif -#ifdef CONFIG_ARM_FFA_TRANSPORT +#if defined(CONFIG_ARM_FFA_TRANSPORT) && !defined(CONFIG_SANDBOX_FFA) ffa_bus_discover, #endif #ifdef CONFIG_POST diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index 290d1506c2..36e6448968 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -248,3 +248,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/configs/sandbox_defconfig b/configs/sandbox_defconfig index ab5d3f19bf..8bf3848788 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -328,3 +328,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/sandbox.rst b/doc/arch/sandbox.rst index 068d4a3be4..5d7e1b2c48 100644 --- a/doc/arch/sandbox.rst +++ b/doc/arch/sandbox.rst @@ -203,6 +203,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 40b467b0a5..263481de96 100644 --- a/drivers/firmware/arm-ffa/Kconfig +++ b/drivers/firmware/arm-ffa/Kconfig @@ -2,8 +2,8 @@ config ARM_FFA_TRANSPORT bool "Enable Arm Firmware Framework for Armv8-A driver" - depends on DM && ARM64 - select ARM_SMCCC + depends on DM && (ARM64 || SANDBOX) + select ARM_SMCCC if !SANDBOX select CMD_ARMFFA select LIB_UUID select DEVRES @@ -38,3 +38,9 @@ config ARM_FFA_EFI_RUNTIME_MODE The driver Code needed at runtime is placed at EFI runtime code section. Turning this on makes ffa_copy_runtime_data available for use and the driver code placed at EFI runtime code section. + +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 0b9b0a61b4..d50060b836 100644 --- a/drivers/firmware/arm-ffa/Makefile +++ b/drivers/firmware/arm-ffa/Makefile @@ -5,3 +5,4 @@ obj-y += arm-ffa-uclass.o core.o obj-$(CONFIG_ARM_FFA_EFI_RUNTIME_MODE) += efi_ffa_runtime_data_mgr.o +obj-$(CONFIG_SANDBOX_FFA) += sandbox.o diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h index 7bc90f7f66..3e0d4c112c 100644 --- a/drivers/firmware/arm-ffa/arm_ffa_prv.h +++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h @@ -19,6 +19,16 @@ /* 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 +typedef struct arm_smccc_1_2_regs ffa_value_t; +#endif + +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) @@ -94,11 +104,6 @@ struct ffa_abi_errmap { #define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1) #define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID) -/* The FF-A SMC function definitions */ - -typedef struct arm_smccc_1_2_regs ffa_value_t; -typedef void (*invoke_ffa_fn_t)(ffa_value_t args, ffa_value_t *res); - /* * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET * @a1-4: 32-bit words access to the UUID data diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c index 41c7b96e68..caba10caae 100644 --- a/drivers/firmware/arm-ffa/core.c +++ b/drivers/firmware/arm-ffa/core.c @@ -1101,6 +1101,7 @@ static int __ffa_runtime ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_sen return ffa_to_std_errno(ffa_errno); } +#if !CONFIG_IS_ENABLED(SANDBOX_FFA) /** * __arm_ffa_fn_smc - SMC wrapper * @args: FF-A ABI arguments to be copied to Xn registers @@ -1114,6 +1115,7 @@ void __ffa_runtime __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res) { arm_smccc_1_2_smc(&args, res); } +#endif /** * ffa_set_smc_conduit - Set the SMC conduit @@ -1127,7 +1129,12 @@ void __ffa_runtime __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res) */ static int ffa_set_smc_conduit(void) { - ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc; +#if CONFIG_IS_ENABLED(SANDBOX_FFA) + ffa_priv_data->invoke_ffa_fn = sandbox_arm_ffa_smccc_smc; + ffa_info("Using SMC emulation"); +#else + ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_smc; +#endif if (!ffa_priv_data->invoke_ffa_fn) { ffa_err("failure to set the invoke function"); @@ -1304,17 +1311,18 @@ struct ffa_prvdata **ffa_bus_prvdata_get(void) } /** - * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device + * ffa_bus_discover - discover FF-A bus and probe arm_ffa and sandbox_arm_ffa devices * * This boot time function makes sure the FF-A bus is discoverable. - * Then, the arm_ffa device is probed and ready to use. + * Then, the arm_ffa and sandbox_arm_ffa devices are ready to use. + * * This function is called automatically at initcalls * level (after u-boot relocation). * * When the bus was already discovered successfully the discovery will not run again. * * Arm FF-A transport is implemented through arm_ffa u-boot device managing the FF-A - * communication. + * communication. In Sandbox mode sandbox_arm_ffa is used to test arm_ffa driver. * All FF-A clients should use the arm_ffa device to use the FF-A transport. * * Return: @@ -1325,9 +1333,15 @@ int ffa_bus_discover(void) { int ret = 0; - if (!ffa_priv_data) + if (!ffa_priv_data) { ret = ffa_device_get(); +#if CONFIG_IS_ENABLED(SANDBOX_FFA) + if (ret == 0) + ret = sandbox_ffa_device_get(); +#endif + } + return ret; } diff --git a/drivers/firmware/arm-ffa/sandbox.c b/drivers/firmware/arm-ffa/sandbox.c new file mode 100644 index 0000000000..16e1fdc809 --- /dev/null +++ b/drivers/firmware/arm-ffa/sandbox.c @@ -0,0 +1,659 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2022 ARM Limited + * Abdellatif El Khlifi + */ + +#include "sandbox_arm_ffa_prv.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/** + * The device private data structure containing all the emulated secure world data + */ +static struct sandbox_ffa_prvdata sandbox_ffa_priv_data = {0}; + +/* 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_get_device - probes the sandbox_arm_ffa device + * + * This function makes sure the sandbox_arm_ffa device is probed + * This function makes sure the sandbox_arm_ffa device is + * created, bound to this driver, probed and ready to use. + * + * sandbox_arm_ffa depends on arm_ffa device. This dependency is + * handled by ffa_bus_discover function. arm_ffa is probed first then + * sandbox_arm_ffa. + * + * Return: + * + * 0 on success. Otherwise, failure + */ +int sandbox_ffa_device_get(void) +{ + int ret; + + if (sandbox_ffa_priv_data.dev) + return 0; + + ret = device_bind(dm_root(), + DM_DRIVER_GET(sandbox_arm_ffa), + FFA_SANDBOX_DRV_NAME, + NULL, + ofnode_null(), + &sandbox_ffa_priv_data.dev); + if (ret) { + sandbox_ffa_priv_data.dev = NULL; + return ret; + } + + ret = device_probe(sandbox_ffa_priv_data.dev); + if (ret) { + ffa_err("[Sandbox] can not probe the device"); + device_unbind(sandbox_ffa_priv_data.dev); + sandbox_ffa_priv_data.dev = NULL; + return ret; + } + + return 0; +} + +/** + * sandbox_ffa_version - Emulated FFA_VERSION handler function + * @{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) +{ + sandbox_ffa_priv_data.fwk_version = FFA_VERSION_1_0; + res->a0 = sandbox_ffa_priv_data.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 + * @{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) +{ + res->a0 = FFA_SMC_32(FFA_SUCCESS); + res->a1 = 0; + + sandbox_ffa_priv_data.id = NS_PHYS_ENDPOINT_ID; + res->a2 = sandbox_ffa_priv_data.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 + * @{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)); + ffa_err("[Sandbox] FF-A interface 0x%lx not implemented", pargs->a1); + } + + res->a1 = 0; + + return 0; +} + +/** + * sandbox_ffa_partition_info_get - Emulated FFA_PARTITION_INFO_GET handler function + * @{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; + + res->a0 = FFA_SMC_32(FFA_ERROR); + + if (!sandbox_ffa_priv_data.pair.rxbuf) { + res->a2 = FFA_ERR_STAT_DENIED; + goto cleanup; + } + + if (sandbox_ffa_priv_data.pair_info.rxbuf_owned) { + res->a2 = FFA_ERR_STAT_BUSY; + goto cleanup; + } + + if (!sandbox_ffa_priv_data.partitions.descs) { + sandbox_ffa_priv_data.partitions.descs = sandbox_partitions; + sandbox_ffa_priv_data.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 ((sandbox_ffa_priv_data.pair_info.rxtx_buf_size * SZ_4K) < descs_size_bytes) { + res->a2 = FFA_ERR_STAT_NO_MEMORY; + goto cleanup; + } + + rxbuf_desc_info = (struct ffa_partition_info *)sandbox_ffa_priv_data.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++) = + sandbox_ffa_priv_data.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 */ + sandbox_ffa_priv_data.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 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].sp_uuid.a1 && + pargs->a2 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].sp_uuid.a2 && + pargs->a3 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].sp_uuid.a3 && + pargs->a4 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].sp_uuid.a4) { + *(rxbuf_desc_info++) = + sandbox_ffa_priv_data.partitions.descs[descs_cnt].info; + } + + if (rxbuf_desc_info != ((struct ffa_partition_info *)sandbox_ffa_priv_data.pair.rxbuf)) { + res->a0 = FFA_SMC_32(FFA_SUCCESS); + /* store the partitions count */ + res->a2 = (unsigned long) + (rxbuf_desc_info - (struct ffa_partition_info *) + sandbox_ffa_priv_data.pair.rxbuf); + + /* transfer ownership to the consumer: the non secure world */ + sandbox_ffa_priv_data.pair_info.rxbuf_owned = 1; + } else { + /* Unrecognized UUID */ + res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS; + } + +cleanup: + + ffa_err("[Sandbox] FFA_PARTITION_INFO_GET (%ld)", 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 + * @{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) +{ + res->a0 = FFA_SMC_32(FFA_ERROR); + + if (sandbox_ffa_priv_data.pair.txbuf && sandbox_ffa_priv_data.pair.rxbuf) { + res->a2 = FFA_ERR_STAT_DENIED; + goto feedback; + } + + if (pargs->a3 >= RXTX_BUFFERS_MIN_PAGES && pargs->a1 && pargs->a2) { + sandbox_ffa_priv_data.pair.txbuf = pargs->a1; + sandbox_ffa_priv_data.pair.rxbuf = pargs->a2; + sandbox_ffa_priv_data.pair_info.rxtx_buf_size = pargs->a3; + sandbox_ffa_priv_data.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; + + ffa_err("[Sandbox] error in FFA_RXTX_MAP arguments (%d)", (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 + * @{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) +{ + res->a0 = FFA_SMC_32(FFA_ERROR); + res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS; + + if (GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != sandbox_ffa_priv_data.id) + goto feedback; + + if (sandbox_ffa_priv_data.pair.txbuf && sandbox_ffa_priv_data.pair.rxbuf) { + sandbox_ffa_priv_data.pair.txbuf = 0; + sandbox_ffa_priv_data.pair.rxbuf = 0; + sandbox_ffa_priv_data.pair_info.rxtx_buf_size = 0; + sandbox_ffa_priv_data.pair_info.rxbuf_mapped = 0; + res->a0 = FFA_SMC_32(FFA_SUCCESS); + res->a2 = 0; + goto feedback; + } + + ffa_err("[Sandbox] No buffer pair registered on behalf of the caller"); + +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 + * @{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) +{ + if (!sandbox_ffa_priv_data.pair_info.rxbuf_owned) { + res->a0 = FFA_SMC_32(FFA_ERROR); + res->a2 = FFA_ERR_STAT_DENIED; + } else { + sandbox_ffa_priv_data.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 + * @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(u16 part_id) +{ + u32 descs_cnt; + + for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++) + if (sandbox_ffa_priv_data.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 + * @{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. + * + * 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; + + part_id = GET_DST_SP_ID(pargs->a1); + + if ((GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != sandbox_ffa_priv_data.id) || + !sandbox_ffa_sp_valid(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(sandbox_ffa_priv_data.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_prv_data - Returns the pointer to FF-A core pivate data + * @func_data: Pointer to the FF-A function arguments container structure + * + * This is the handler that returns the address of the FF-A core pivate data. + * + * Return: + * + * 0 on success. Otherwise, failure + */ +static int sandbox_ffa_get_prv_data(struct ffa_sandbox_data *func_data) +{ + if (!func_data) + return -EINVAL; + + if (!func_data->data0 || func_data->data0_size != sizeof(struct ffa_prvdata **)) + return -EINVAL; + + if (!func_data->data1 || func_data->data1_size != sizeof(struct sandbox_ffa_prvdata **)) + return -EINVAL; + + *((struct ffa_prvdata **)func_data->data0) = *(ffa_bus_prvdata_get()); + *((struct sandbox_ffa_prvdata **)func_data->data1) = &sandbox_ffa_priv_data; + + return 0; +} + +/** + * sandbox_ffa_get_rxbuf_flags - Reading the mapping/ownership flags + * @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(u32 queried_func_id, struct ffa_sandbox_data *func_data) +{ + 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) = sandbox_ffa_priv_data.pair_info.rxbuf_mapped; + return 0; + case FFA_RX_RELEASE: + *((u8 *)func_data->data0) = sandbox_ffa_priv_data.pair_info.rxbuf_owned; + return 0; + default: + ffa_err("[Sandbox] The querried FF-A interface flag (%d) undefined", + queried_func_id); + return -EINVAL; + } +} + +/** + * sandbox_ffa_query_core_state - The driver dispatcher function + * @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(u32 queried_func_id, struct ffa_sandbox_data *func_data) +{ + switch (queried_func_id) { + case FFA_VERSION: + case FFA_ID_GET: + case FFA_FEATURES: + return sandbox_ffa_get_prv_data(func_data); + case FFA_RXTX_MAP: + case FFA_RXTX_UNMAP: + case FFA_RX_RELEASE: + return sandbox_ffa_get_rxbuf_flags(queried_func_id, func_data); + default: + ffa_err("[Sandbox] The querried FF-A interface (%d) undefined", 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; + + switch (args.a0) { + case FFA_SMC_32(FFA_VERSION): + ret = sandbox_ffa_version(&args, res); + break; + case FFA_SMC_32(FFA_PARTITION_INFO_GET): + ret = sandbox_ffa_partition_info_get(&args, res); + break; + case FFA_SMC_32(FFA_RXTX_UNMAP): + ret = sandbox_ffa_rxtx_unmap(&args, res); + break; + case FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ): + ret = sandbox_ffa_msg_send_direct_req(&args, res); + break; + case FFA_SMC_32(FFA_ID_GET): + ret = sandbox_ffa_id_get(&args, res); + break; + case FFA_SMC_32(FFA_FEATURES): + ret = sandbox_ffa_features(&args, res); + break; + case FFA_SMC_64(FFA_RXTX_MAP): + ret = sandbox_ffa_rxtx_map(&args, res); + break; + case FFA_SMC_32(FFA_RX_RELEASE): + ret = sandbox_ffa_rx_release(&args, res); + break; + default: + ffa_err("[Sandbox] Undefined FF-A interface (0x%lx)", args.a0); + } + + if (ret != 0) + ffa_err("[Sandbox] FF-A ABI internal failure (%d)", ret); +} + +/** + * sandbox_ffa_probe - The driver probe function + * @dev: the sandbox_arm_ffa device + * + * Return: + * + * 0 on success. Otherwise, failure + */ +static int sandbox_ffa_probe(struct udevice *dev) +{ + return 0; +} + +/** + * sandbox_ffa_remove - The driver remove function + * @dev: the sandbox_arm_ffa device + * + * Return: + * + * 0 on success. Otherwise, failure + */ +static int sandbox_ffa_remove(struct udevice *dev) +{ + ffa_info("[Sandbox] removing the device"); + memset(&sandbox_ffa_priv_data, 0, sizeof(sandbox_ffa_priv_data)); + return 0; +} + +/** + * Declaring the sandbox_arm_ffa driver under UCLASS_FFA + */ +U_BOOT_DRIVER(sandbox_arm_ffa) = { + .name = FFA_SANDBOX_DRV_NAME, + .id = UCLASS_FFA, + .probe = sandbox_ffa_probe, + .remove = sandbox_ffa_remove, +}; diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h new file mode 100644 index 0000000000..4db57f5092 --- /dev/null +++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2022 ARM Limited + * Abdellatif El Khlifi + */ + +#ifndef __SANDBOX_ARM_FFA_PRV_H +#define __SANDBOX_ARM_FFA_PRV_H + +#include "arm_ffa_prv.h" +#include + +/* + * This header is private. It is exclusively used by the Sandbox FF-A driver + */ + +/* 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 + +/* 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)) + +/* 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) + +/* secure partitions count */ +#define SANDBOX_PARTITIONS_CNT (4) + +/* 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_prvdata - 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_prvdata { + 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(ffa_value_t *pargs, ffa_value_t *res) + +#endif diff --git a/include/arm_ffa.h b/include/arm_ffa.h index f17b100497..665413a0c5 100644 --- a/include/arm_ffa.h +++ b/include/arm_ffa.h @@ -111,7 +111,7 @@ struct ffa_bus_ops { const struct ffa_bus_ops * __ffa_runtime ffa_bus_ops_get(void); /** - * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device + * ffa_bus_discover - discover FF-A bus and probes the arm_ffa and sandbox_arm_ffa devices */ int ffa_bus_discover(void); diff --git a/include/sandbox_arm_ffa.h b/include/sandbox_arm_ffa.h new file mode 100644 index 0000000000..d5df16f282 --- /dev/null +++ b/include/sandbox_arm_ffa.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2022 ARM Limited + * Abdellatif El Khlifi + */ + +#ifndef __SANDBOX_ARM_FFA_H +#define __SANDBOX_ARM_FFA_H + +#include + +/** + * 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 of services supported by the sandbox driver */ +#define SANDBOX_SERVICE1_UUID "ed32d533-4209-99e6-2d72-cdd998a79cc0" +#define SANDBOX_SERVICE2_UUID "ed32d544-4209-99e6-2d72-cdd998a79cc0" +#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" + +#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 - Queries the status of FF-A ABIs + */ +int sandbox_ffa_query_core_state(u32 queried_func_id, struct ffa_sandbox_data *func_data); + +/** + * sandbox_ffa_get_device - create, bind and probe the sandbox_arm_ffa device + */ +int sandbox_ffa_device_get(void); + +/** + * sandbox_arm_ffa_smccc_smc - FF-A SMC call emulation + */ +void sandbox_arm_ffa_smccc_smc(ffa_value_t args, ffa_value_t *res); + +#endif diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index af0b0f3db1..d404343a7d 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -2185,7 +2185,7 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); } -#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) && !CONFIG_IS_ENABLED(SANDBOX_FFA) /* unmap FF-A RX/TX buffers */ if (ffa_bus_ops_get()->rxtx_unmap()) debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n"); -- 2.17.1