Hi Abdellatif, On Wed, 29 Mar 2023 at 05:12, Abdellatif El Khlifi < abdellatif.elkhl...@arm.com> wrote: > > Emulate Secure World's FF-A ABIs and allow testing U-Boot FF-A support > > Features of the sandbox FF-A support: > > - Introduce an FF-A emulator > - Introduce an FF-A device driver for FF-A comms with emulated Secure World > - Provides test methods allowing to read the status of the inspected ABIs > > The sandbox FF-A emulator supports only 64-bit direct messaging. > > Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhl...@arm.com> > Cc: Tom Rini <tr...@konsulko.com> > Cc: Simon Glass <s...@chromium.org> > Cc: Ilias Apalodimas <ilias.apalodi...@linaro.org> > Cc: Jens Wiklander <jens.wiklan...@linaro.org> > Cc: Heinrich Schuchardt <xypron.g...@gmx.de> > > --- > Changelog: > =============== > > v10: > > * split the FF-A sandbox support into an emulator and a driver > * read FFA_VERSION and FFA_PARTITION_INFO_GET state using > sandbox_ffa_query_core_state() > * drop CONFIG_SANDBOX_FFA config > * address nits > > 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 | 3 +- > arch/sandbox/dts/sandbox.dtsi | 8 + > arch/sandbox/dts/test.dts | 8 + > arch/sandbox/include/asm/sandbox_arm_ffa.h | 68 ++ > .../include/asm/sandbox_arm_ffa_priv.h | 133 ++++ > configs/sandbox64_defconfig | 1 + > configs/sandbox_defconfig | 1 + > doc/arch/arm64.ffa.rst | 7 +- > doc/arch/sandbox/sandbox.rst | 1 + > drivers/firmware/arm-ffa/Kconfig | 13 +- > drivers/firmware/arm-ffa/Makefile | 10 +- > drivers/firmware/arm-ffa/ffa-emul-uclass.c | 732 ++++++++++++++++++ > .../firmware/arm-ffa/sandbox_arm_ffa_priv.h | 14 - > drivers/firmware/arm-ffa/sandbox_ffa.c | 108 +++ > include/dm/uclass-id.h | 1 + > 15 files changed, 1087 insertions(+), 21 deletions(-) > create mode 100644 arch/sandbox/include/asm/sandbox_arm_ffa.h > create mode 100644 arch/sandbox/include/asm/sandbox_arm_ffa_priv.h > create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c > delete mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h > create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c >
[..] > +/** > + * sandbox_ffa_get_fwk_version() - Return the FFA framework version > + * @dev: The sandbox FF-A emulator device > + * @func_data: Pointer to the FF-A function arguments container structure > + * > + * Return the FFA framework version read from the FF-A emulator data. > + * > + * Return: > + * > + * 0 on success. Otherwise, failure > + */ > +static int sandbox_ffa_get_fwk_version(struct udevice *dev, struct ffa_sandbox_data *func_data) > +{ > + struct sandbox_ffa_emul *priv = dev_get_priv(dev); > + > + if (!func_data) > + return -EINVAL; > + > + if (!func_data->data0 || > + func_data->data0_size != sizeof(priv->fwk_version)) > + return -EINVAL; > + > + *((u32 *)func_data->data0) = priv->fwk_version; > + > + return 0; > +} > + > +/** > + * sandbox_ffa_get_parts() - Return the address of partitions data > + * @dev: The sandbox FF-A emulator device > + * @func_data: Pointer to the FF-A function arguments container structure > + * > + * Return the address of partitions data read from the FF-A emulator data. > + * > + * Return: > + * > + * 0 on success. Otherwise, failure > + */ > +static int sandbox_ffa_get_parts(struct udevice *dev, struct ffa_sandbox_data *func_data) > +{ > + struct sandbox_ffa_emul *priv = dev_get_priv(dev); > + > + if (!func_data) > + return -EINVAL; > + > + if (!func_data->data0 || > + func_data->data0_size != sizeof(struct ffa_partitions *)) > + return -EINVAL; > + > + *((struct ffa_partitions **)func_data->data0) = &priv->partitions; > + > + return 0; > +} > + > +/** > + * sandbox_ffa_query_core_state() - Inspect the FF-A ABIs > + * @queried_func_id: The FF-A function to be queried > + * @func_data: Pointer to the FF-A function arguments container structure > + * > + * 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) > +{ > + struct udevice *dev; Please can you use 'emul' for the emulator so it is separate from the device? > + > + uclass_first_device(UCLASS_FFA_EMUL, &dev); > + if (!dev) { > + log_err("[FFA][SANDBOX][Emul] Cannot find FF-A emulator during querying state\n"); > + return -ENODEV; > + } How about storing the emulator somewhere? You could have: struct sandbox_ffa_priv { struct udevice *emul; }; .priv = sizeof(sandbox_ffa_priv) > + > + 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); > + case FFA_VERSION: > + return sandbox_ffa_get_fwk_version(dev, func_data); > + case FFA_PARTITION_INFO_GET: > + return sandbox_ffa_get_parts(dev, func_data); > + default: > + log_err("[FFA][Sandbox][Emul] 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 > + * > + * Emulates the FF-A ABIs SMC call. > + * The emulated FF-A ABI is identified and invoked. > + * FF-A emulation is based on the FF-A specification 1.0 > + * > + * Return: > + * > + * 0 on success. Otherwise, failure. > + * FF-A protocol error codes are returned using the registers arguments as > + * described by the specification > + */ > +void sandbox_arm_ffa_smccc_smc(ffa_value_t args, ffa_value_t *res) > +{ > + int ret = 0; > + struct udevice *dev; > + > + uclass_first_device(UCLASS_FFA_EMUL, &dev); > + if (!dev) { > + log_err("[FFA][SANDBOX][Emul] Cannot find FF-A emulator during SMC emulation\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(&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][Emul] Undefined FF-A interface (0x%lx)\n", > + args.a0); > + } > + > + if (ret != 0) > + log_err("[FFA][Sandbox][Emul] FF-A ABI internal failure (%d)\n", ret); > +} > + > +/** > + * ffa_emul_find() - Finds the FF-A emulator > + * @dev: the sandbox FF-A device (sandbox-arm-ffa) > + * @emulp: the FF-A emulator device (sandbox-ffa-emul) > + * > + * Searches for the FF-A emulator and returns its device pointer. > + * > + * Return: > + * 0 on success. Otherwise, failure > + */ > +int ffa_emul_find(struct udevice *dev, struct udevice **emulp) > +{ > + if (!emulp) > + return -EINVAL; > + > + *emulp = NULL; > + > + uclass_first_device(UCLASS_FFA_EMUL, emulp); > + if (!(*emulp)) { > + log_err("[FFA][SANDBOX][Emul] Cannot find FF-A emulator\n"); > + return -ENODEV; > + } > + > + log_info("[FFA][Sandbox][Emul] FF-A emulator found\n"); > + > + return 0; > +} > + > +UCLASS_DRIVER(ffa_emul) = { > + .name = "ffa_emul", > + .id = UCLASS_FFA_EMUL, > +}; > + > +/* Sandbox Arm FF-A emulator operations */ > + > +static const struct ffa_emul_ops sandbox_ffa_emul_ops = { > + .invoke_ffa_fn = sandbox_arm_ffa_smccc_smc, > +}; > + > +static const struct udevice_id sandbox_ffa_emul_ids[] = { > + { .compatible = "sandbox,arm-ffa-emul" }, > + { } > +}; > + > +/* Declaring the sandbox FF-A emulator under UCLASS_FFA_EMUL */ > +U_BOOT_DRIVER(sandbox_ffa_emul) = { > + .name = "sandbox_ffa_emul", > + .id = UCLASS_FFA_EMUL, > + .of_match = sandbox_ffa_emul_ids, > + .ops = &sandbox_ffa_emul_ops, > + .priv_auto = sizeof(struct sandbox_ffa_emul), > +}; > diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h > deleted file mode 100644 > index 4338f9c9b1..0000000000 > --- a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h > +++ /dev/null > @@ -1,14 +0,0 @@ > -/* SPDX-License-Identifier: GPL-2.0+ */ > -/* > - * Copyright 2022-2023 Arm Limited and/or its affiliates < open-source-off...@arm.com> > - * > - * Authors: > - * Abdellatif El Khlifi <abdellatif.elkhl...@arm.com> > - */ > - > -#ifndef __SANDBOX_ARM_FFA_PRV_H > -#define __SANDBOX_ARM_FFA_PRV_H > - > -/* Future sandbox support private declarations */ > - > -#endif > diff --git a/drivers/firmware/arm-ffa/sandbox_ffa.c b/drivers/firmware/arm-ffa/sandbox_ffa.c > new file mode 100644 > index 0000000000..bb150fd5cd > --- /dev/null > +++ b/drivers/firmware/arm-ffa/sandbox_ffa.c > @@ -0,0 +1,108 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Copyright 2022-2023 Arm Limited and/or its affiliates < open-source-off...@arm.com> > + * > + * Authors: > + * Abdellatif El Khlifi <abdellatif.elkhl...@arm.com> > + */ > +#include <common.h> > +#include <arm_ffa.h> > +#include <dm.h> > +#include <log.h> > +#include <asm/global_data.h> > +#include <asm/sandbox_arm_ffa_priv.h> > +#include <dm/device-internal.h> > +#include <linux/errno.h> > + > +DECLARE_GLOBAL_DATA_PTR; > + > +/** > + * ffa_set_smc_conduit() - Set the SMC conduit > + * > + * Selects the SMC conduit by setting the FF-A ABI invoke function. > + * The function emulating the SMC call is provided by the FF-A emulator. > + * > + * Return: > + * > + * 0 on success. Otherwise, failure > + */ > +int ffa_set_smc_conduit(void) > +{ > + struct udevice *emul; > + int ret; > + > + ret = ffa_emul_find(NULL, &emul); > + if (ret) { > + log_err("[FFA][Sandbox] Cannot find FF-A emulator, SMC emulation failure\n"); > + return -ENODEV; > + } > + > + if (!ffa_emul_get_ops(emul)->invoke_ffa_fn) { > + log_err("[FFA][Sandbox] Cannot get FF-A emulator ops, SMC emulation failure\n"); > + return -ENOSYS; > + } > + > + dscvry_info.invoke_ffa_fn = ffa_emul_get_ops(emul)->invoke_ffa_fn; > + log_info("[FFA][Sandbox] Using emulated Arm SMC for FF-A conduit\n"); > + > + return 0; > +} > + > +/** > + * sandbox_ffa_probe() - The sandbox FF-A driver probe function > + * @dev: the sandbox Arm FF-A bus device (sandbox-arm-ffa) > + * > + * Probing is done through ffa_do_probe() > + * > + * Return: > + * > + * 0 on success. Otherwise, failure > + */ > +static int sandbox_ffa_probe(struct udevice *dev) > +{ > + return ffa_do_probe(dev); Move to a uclass pre_probe() method. > +} Drop this. You can add it in the uclass as a child_pre_probe member. > + > +/** > + * sandbox_ffa_bind() - The sandbox FF-A driver bind function > + * @dev: the sandbox-arm-ffa device > + * Tries to discover the emulated FF-A bus. > + * Return: > + * > + * 0 on success. > + */ > +static int sandbox_ffa_bind(struct udevice *dev) > +{ > + bool ret; > + > + log_info("[FFA][Sandbox] binding the device\n"); > + > + ret = ffa_try_discovery(); The code for this is immediately above. Just do that here, or make the above function static and rename it. > + if (ret) > + return 0; > + else > + return -ENODEV; if (ret) return ret; return 0; > +} > + > +/* Sandbox Arm FF-A emulator operations */ > + > +static const struct ffa_bus_ops sandbox_ffa_ops = { > + .partition_info_get = ffa_get_partitions_info_hdlr, > + .sync_send_receive = ffa_msg_send_direct_req_hdlr, > + .rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr, > +}; > + > +static const struct udevice_id sandbox_ffa_id[] = { > + { "sandbox,arm-ffa", 0 }, > + { }, > +}; > + > +/* Declaring the sandbox FF-A driver under UCLASS_FFA */ > +U_BOOT_DRIVER(sandbox_arm_ffa) = { > + .name = "sandbox_arm_ffa", > + .of_match = sandbox_ffa_id, > + .id = UCLASS_FFA, > + .probe = sandbox_ffa_probe, > + .bind = sandbox_ffa_bind, > + .ops = &sandbox_ffa_ops, > +}; > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h > index df77c7da58..4658411935 100644 > --- a/include/dm/uclass-id.h > +++ b/include/dm/uclass-id.h > @@ -61,6 +61,7 @@ enum uclass_id { > UCLASS_ETH, /* Ethernet device */ > UCLASS_ETH_PHY, /* Ethernet PHY device */ > UCLASS_FFA, /* Arm Firmware Framework for Armv8-A */ > + UCLASS_FFA_EMUL, /* sandbox FF-A device emulator */ > UCLASS_FIRMWARE, /* Firmware */ > UCLASS_FPGA, /* FPGA device */ > UCLASS_FUZZING_ENGINE, /* Fuzzing engine */ > -- > 2.25.1 > Regards, Simon