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 74BE3C00140 for ; Fri, 12 Aug 2022 07:40:13 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id AD26C84AD3; Fri, 12 Aug 2022 09:40:10 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="oyC5Wppz"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 03AF984AD3; Fri, 12 Aug 2022 09:40:09 +0200 (CEST) Received: from mail-yw1-x112a.google.com (mail-yw1-x112a.google.com [IPv6:2607:f8b0:4864:20::112a]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id AF1D884ACC for ; Fri, 12 Aug 2022 09:40:01 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=ilias.apalodimas@linaro.org Received: by mail-yw1-x112a.google.com with SMTP id 00721157ae682-31f661b3f89so2433557b3.11 for ; Fri, 12 Aug 2022 00:40:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc; bh=+FuW4VZMPXPkmUjlFrnb0ex0T3z4nFHUGUDUSpwgM+8=; b=oyC5WppzWN/XlG7zcY3AyzE2kiJtnP5uJ55Eh3cvjooxHvo/msKzK+AMhHmg9kshj7 9SAGvrqmgZBI5q/8CpRYNDO0UxuqS3jZxTcnFRa6TmwqvuYSPtCmqbGNvrErWGWLbZs/ jtC1WnjI4ypCnN+uSv8Ns6UOg7tM8d6ErM3svgwZlnQ8B38OtZd1n+GgiL0MGS0MspNm gcP4XVFjyTEFvTEgnP1N0ltkd8qVpdzgc5loHyJcEsDekkR2CJIs9+dt/rU2ArGg5i5S RdMoOP4uZpOY09XuX5ldQ7jCA62NkKtQAAqgxzGNLxZ48YrTtVT5SrqqtltC9+RT1Kj2 LwNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc; bh=+FuW4VZMPXPkmUjlFrnb0ex0T3z4nFHUGUDUSpwgM+8=; b=p0SnbTDGjmH5qkerkUJYh1pLlrLOydJa2lyQpiMvL6uH5QXxpAxCr36RfCcO2801Nx Mrf92PjDv/pImkjUqFOHLsMHTdqrrLgJ9DOssdxvneMhPQlutJpU3N8STkTy7KEaSrk8 SGTUP616j8FQjRiVdG3pV8dHU+wYBiTXWA3TWd4lyUACt0SSLf4HdN4z+mFsl3YYFgRa W8xqSpCcdCt/EK+TTm7FOZ2g+WNtwXE8DLJPn9doW3ygK52pZw8QYuG6o2lBAw+xXVrc q3uzO8GEbG0s7mVdXC97/bJjMIBPMRVnTP/3xMpozA7U5RoKRMBeF+Rw5Gtzsi8JjSPV Z0cw== X-Gm-Message-State: ACgBeo1xzJZ3409LxbxIeLW+ALQEVScepGkH1wDZXHWfJdY4VnX+9dvI v6bL8Oodqg8NczZs3qbLmpb+M6m3710iYDD+hhPNMA== X-Google-Smtp-Source: AA6agR7qKzIKLw3Dv2erXU/muRaK5GGtmQdUqkR4jbP+vL4FgEcj94ZsLDLdnSk6XjJaXLqhDgzooh8UxAM8cCwBggs= X-Received: by 2002:a81:6a07:0:b0:323:8614:10c2 with SMTP id f7-20020a816a07000000b00323861410c2mr2745645ywc.191.1660290000136; Fri, 12 Aug 2022 00:40:00 -0700 (PDT) MIME-Version: 1.0 References: <20220801172053.20163-1-abdellatif.elkhlifi@arm.com> <20220801172053.20163-4-abdellatif.elkhlifi@arm.com> In-Reply-To: <20220801172053.20163-4-abdellatif.elkhlifi@arm.com> From: Ilias Apalodimas Date: Fri, 12 Aug 2022 10:39:23 +0300 Message-ID: Subject: Re: [PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver To: Abdellatif El Khlifi Cc: jens.wiklander@linaro.org, achin.gupta@arm.com, trini@konsulko.com, u-boot@lists.denx.de, vishnu.banavath@arm.com, xueliang.zhong@arm.com, nd@arm.com Content-Type: text/plain; charset="UTF-8" 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 Hi Abdellatif, On Mon, 1 Aug 2022 at 20:21, Abdellatif El Khlifi wrote: > > Add the driver implementing Arm Firmware Framework for Armv8-A v1.0 > > 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 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. > > 32-bit version of the ABIs is supported and 64-bit version of FFA_RXTX_MAP > and FFA_MSG_SEND_DIRECT_{REQ, RESP}. > > In u-boot FF-A design, FF-A is considered as a discoverable bus. > 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 > > This implementation provides an optional feature to copy the driver data > to EFI runtime area. > [...] > +config ARM_FFA_TRANSPORT > + bool "Enable Arm Firmware Framework for Armv8-A driver" > + depends on DM && ARM64 > + select ARM_SMCCC > + 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. > + 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. > + > +config ARM_FFA_EFI_RUNTIME_MODE > + bool "Enable EFI runtime support for FF-A data and code " > + depends on ARM_FFA_TRANSPORT && EFI_LOADER > + help > + Allows FF-A driver data structures and code to be accessible at EFI runtime Is there a reason we want to opt-in on that? What prevents it from always being there? [...] > + > +/* 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)) > + > +#define FFA_VERSION FFA_SMC_32(0x63) > +#define FFA_ID_GET FFA_SMC_32(0x69) > +#define FFA_FEATURES FFA_SMC_32(0x64) > +#define FFA_PARTITION_INFO_GET FFA_SMC_32(0x68) > +#define FFA_RXTX_UNMAP FFA_SMC_32(0x67) > +#define FFA_RX_RELEASE FFA_SMC_32(0x65) > +#define FFA_RUN FFA_SMC_32(0x6D) > +#define FFA_ERROR FFA_SMC_32(0x60) > +#define FFA_SUCCESS FFA_SMC_32(0x61) > +#define FFA_INTERRUPT FFA_SMC_32(0x62) > +#define FFA_RXTX_MAP FFA_SMC_64(0x66) > +#define FFA_MSG_SEND_DIRECT_REQ FFA_SMC_64(0x6F) > +#define FFA_MSG_SEND_DIRECT_RESP FFA_SMC_64(0x70) > + > +/* 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); > + > +/* FF-A error codes */ > +#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_INTERRUPTED (-5) > +#define FFA_ERR_STAT_DENIED (-6) > +#define FFA_ERR_STAT_RETRY (-7) > +#define FFA_ERR_STAT_ABORTED (-8) > + > +/* UUID data size */ > +#define UUID_SIZE (16) Please drop () on these > + > +/* > + * union ffa_partition_uuid - Data union hosting the UUID > + * transmitted by FFA_PARTITION_INFO_GET > + * @words: data structure giving 32-bit words access to the UUID data > + * @bytes: data structure giving byte access to the UUID data > + * > + * The structure holds little-endian UUID data. > + */ > +union ffa_partition_uuid { > + struct __packed words { > + u32 a1; /* w1 */ > + u32 a2; /* w2 */ > + u32 a3; /* w3 */ > + u32 a4; /* w4 */ > + } words; > + u8 bytes[UUID_SIZE]; > +}; is the bytes field used anywhere? [...] > + * > + * Each partition has its descriptor containing the partitions information and the UUID > + */ > +struct ffa_partition_desc { > + struct ffa_partition_info info; > + union ffa_partition_uuid UUID; lower case please and perhaps a better name e.g partition_uuid > +}; > + > +/** > + * struct ffa_partitions - descriptors for all secure partitions > + * @count: The number of partitions descriptors > + * @descs The partitions descriptors table > + * > + * This data structure contains the partitions descriptors table > + */ > +struct ffa_partitions { > + u32 count; > + struct ffa_partition_desc *descs; /* virtual address */ > +}; > + > +/** > + * struct ffa_prvdata - the driver private data structure > + * > + * @dev: The arm_ffa device under u-boot driver model > + * @ffa_ops: The driver operations structure > + * @fwk_version: FF-A framework version > + * @id: u-boot endpoint ID > + * @partitions: The partitions descriptors structure > + * @pair: The RX/TX buffers pair > + * @invoke_ffa_fn: The function executing the FF-A function > + * @features: Table of the FF-A functions having features > + * > + * The driver data structure hosting all resident data. > + */ > +struct ffa_prvdata { > + struct udevice *dev; > + struct ffa_bus_ops ffa_ops; > + u32 fwk_version; > + u16 id; > + struct ffa_partitions partitions; > + struct ffa_rxtxpair pair; > + invoke_ffa_fn_t invoke_ffa_fn; > + struct ffa_features_desc features[FFA_FEATURE_DESC_CNT]; > +}; > + > +/** > + * ffa_device_get - create, bind and probe the arm_ffa device > + */ > +int ffa_device_get(void); > + > +/** > + * ffa_bus_prvdata_get - bus driver private data getter > + */ > +struct ffa_prvdata **ffa_bus_prvdata_get(void); > + > +#endif > diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c > new file mode 100644 > index 0000000000..40d140fc3e > --- /dev/null > +++ b/drivers/arm-ffa/core.c > @@ -0,0 +1,1338 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2022 ARM Limited > + * Abdellatif El Khlifi > + */ > + > +#include "arm_ffa_prv.h" > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +DECLARE_GLOBAL_DATA_PTR; > + > +/** > + * The device private data structure containing all the resident > + * data read from secure world > + */ > +__ffa_runtime_data struct ffa_prvdata *ffa_priv_data; I think it's better if we just keep this as efi_runtime, especially since the rest of the declarations you use are marked as efi_* [...] > + > +/** > + * ffa_device_get - create, bind and probe the arm_ffa device > + * > + * This boot time function makes sure the arm_ffa device is > + * created, bound to this driver, probed and ready to use. > + * Arm FF-A transport is implemented through a single u-boot > + * device managing the FF-A bus (arm_ffa). > + * > + * Return: > + * > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure > + */ > +int ffa_device_get(void) > +{ > + int ret; > + struct udevice *dev = NULL; > + > + if (ffa_priv_data && ffa_priv_data->dev) > + return FFA_ERR_STAT_SUCCESS; > + > + ret = device_bind(dm_root(), > + DM_DRIVER_GET(arm_ffa), > + FFA_DRV_NAME, > + NULL, > + ofnode_null(), > + &dev); > + if (ret) > + return ret; > + > + /* The FF-A bus discovery succeeds when probing is successful */ > + ret = device_probe(dev); > + if (ret) { > + ffa_err("arm_ffa device probing failed"); > + ffa_remove_device(dev); > + return ret; > + } > + > + return FFA_ERR_STAT_SUCCESS; The return values in most of the functions are confusing. I think you should just get rid of FFA_ERR_STAT_SUCCESS and just return 0 [...] > + > + if (!ffa_priv_data->invoke_ffa_fn) > + panic("[FFA] no private data found\n"); Get rid of all the panicking please. We've discussed this on a previous email. Isn't an error message enough? [...] > + * ffa_map_rxtx_buffers - FFA_RXTX_MAP handler function > + * @buf_4k_pages: the minimum number of pages in each of the RX/TX > + * buffers > + * > + * This is the boot time function that implements FFA_RXTX_MAP FF-A function > + * to map the RX/TX buffers > + * > + * Return: > + * > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure > + */ > +static int ffa_map_rxtx_buffers(size_t buf_4k_pages) > +{ > + int ret; > + ffa_value_t res = {0}; > + > + if (!ffa_priv_data->invoke_ffa_fn) > + panic("[FFA] no private data found\n"); > + > + ret = ffa_alloc_rxtx_buffers(buf_4k_pages); > + if (ret != FFA_ERR_STAT_SUCCESS) > + 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 > + */ > + > + ffa_priv_data->invoke_ffa_fn((ffa_value_t){ > + .a0 = FFA_RXTX_MAP, > + .a1 = ffa_priv_data->pair.txbuf, > + .a2 = ffa_priv_data->pair.rxbuf, > + .a3 = buf_4k_pages, > + .a4 = 0, .a5 = 0, .a6 = 0, .a7 = 0, > + }, &res); > + > + switch (res.a0) { > + case FFA_ERROR: > + { There are comments in v2 that are ignored throughout the patchset. Please check the remarks in v2 before sending a new patchset > + switch (((int)res.a2)) { > + case FFA_ERR_STAT_INVALID_PARAMETERS: > + ffa_err("One or more fields in input parameters is incorrectly encoded"); > + ret = -EPERM; > + break; > + case FFA_ERR_STAT_NO_MEMORY: > + ffa_err("Not enough memory"); > + ret = -ENOMEM; > + break; > + case FFA_ERR_STAT_DENIED: > + ffa_err("Buffer pair already registered"); > + ret = -EACCES; > + break; > + case FFA_ERR_STAT_NOT_SUPPORTED: > + ffa_err("This function is not implemented at this FF-A instance"); > + ret = -EOPNOTSUPP; > + break; > + default: > + ffa_err("Undefined error (%d)", > + ((int)res.a2)); > + ret = -EINVAL; > + } > + break; > + } > + case FFA_SUCCESS: > + ffa_info("RX/TX buffers mapped"); > + return FFA_ERR_STAT_SUCCESS; > + default: > + ffa_err("Undefined response function (0x%lx)", > + res.a0); > + ret = -EINVAL; > + } > + > + ffa_free_rxtx_buffers(); > + > + return ret; > +} > + > +/** [...] Regards /Ilias > + > +/** > + * Declaring the arm_ffa driver under UCLASS_FFA > + */ > + > +U_BOOT_DRIVER(arm_ffa) = { > + .name = FFA_DRV_NAME, > + .id = UCLASS_FFA, > + .probe = ffa_probe, > +}; > diff --git a/drivers/arm-ffa/efi_ffa_runtime_data_mgr.c b/drivers/arm-ffa/efi_ffa_runtime_data_mgr.c > new file mode 100644 > index 0000000000..942601a7ba > --- /dev/null > +++ b/drivers/arm-ffa/efi_ffa_runtime_data_mgr.c > @@ -0,0 +1,94 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2022 ARM Limited > + * Abdellatif El Khlifi > + */ > + > +#include "arm_ffa_prv.h" > + > +/** > + * ffa_copy_runtime_data - copy the private data structure to the runtime area > + * > + * This boot time function copies the arm_ffa driver data structures including > + * partitions data to the EFI runtime data section. > + * > + * Return: > + * > + * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure > + */ > +efi_status_t ffa_copy_runtime_data(void) > +{ > + efi_status_t efi_ret; > + efi_uintn_t prvdata_pages; > + efi_uintn_t descs_pages; > + struct ffa_prvdata **prvdata = NULL; /* Pointer to the current structure */ > + struct ffa_prvdata *runtime_prvdata = NULL; /* Pointer to the structure runtime copy */ > + u64 runtime_descs = 0; > + > + prvdata = ffa_bus_prvdata_get(); > + > + printf("INFO: EFI: FFA: prv data area at 0x%llx\n", (u64)prvdata); > + > + /* allocate private data runtime area */ > + > + prvdata_pages = efi_size_in_pages(sizeof(struct ffa_prvdata)); > + efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, > + EFI_RUNTIME_SERVICES_DATA, > + prvdata_pages, > + (u64 *)&runtime_prvdata); > + > + if (efi_ret != EFI_SUCCESS) { > + printf("ERROR: EFI: FFA: allocating runtime data (err: 0x%lx, addr 0x%llx)\n", > + efi_ret, (u64)runtime_prvdata); > + > + return efi_ret; > + } > + > + printf("INFO: EFI: FFA: runtime data area at 0x%llx\n", (u64)runtime_prvdata); > + > + if (!runtime_prvdata) > + return EFI_INVALID_PARAMETER; > + > + /* allocate the partition data runtime area */ > + > + descs_pages = efi_size_in_pages((*prvdata)->partitions.count * > + sizeof(struct ffa_partition_desc)); > + efi_ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, > + EFI_RUNTIME_SERVICES_DATA, > + descs_pages, > + &runtime_descs); > + > + if (efi_ret != EFI_SUCCESS) { > + printf("ERROR: EFI: FFA: allocating runtime SPs data (err: 0x%lx, addr 0x%llx)\n", > + efi_ret, runtime_descs); > + > + efi_free_pages((u64)runtime_prvdata, prvdata_pages); > + > + return efi_ret; > + } > + > + printf("INFO: EFI: FFA: SPs runtime area at 0x%llx\n", (u64)runtime_descs); > + > + if (!runtime_descs) > + return EFI_INVALID_PARAMETER; > + > + *runtime_prvdata = **prvdata; > + > + runtime_prvdata->dev = NULL; > + runtime_prvdata->ffa_ops.partition_info_get = NULL; > + runtime_prvdata->ffa_ops.rxtx_unmap = NULL; > + runtime_prvdata->partitions.descs = (struct ffa_partition_desc *)runtime_descs; > + runtime_prvdata->pair.rxbuf = 0; > + runtime_prvdata->pair.txbuf = 0; > + > + /* > + * Update the private data structure pointer in the driver > + * no need to free the old structure. devm takes care of that > + */ > + *prvdata = runtime_prvdata; > + > + printf("INFO: EFI: FFA: runtime prv data now at 0x%llx , SPs count %d\n", > + (u64)*prvdata, (*prvdata)->partitions.count); > + > + return FFA_ERR_STAT_SUCCESS; > +} > diff --git a/include/arm_ffa.h b/include/arm_ffa.h > new file mode 100644 > index 0000000000..ee9ce2d99d > --- /dev/null > +++ b/include/arm_ffa.h > @@ -0,0 +1,132 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > +/* > + * (C) Copyright 2022 ARM Limited > + * 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 > + */ > + > +/* > + * Macros for displaying logs > + */ > + > +#define ffa_info(fmt, ...) pr_info("[FFA] " fmt "\n", ##__VA_ARGS__) > +#define ffa_err(fmt, ...) pr_err("[FFA] " fmt "\n", ##__VA_ARGS__) > + > +/* > + * The driver operations success error code > + */ > +#define FFA_ERR_STAT_SUCCESS (0) > + > +/* > + * 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 __packed 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 __packed 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 */ > +}; > + > +#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE) > + > +#include > + > +/* > + * __ffa_runtime - controls whether functions are > + * available after calling the EFI ExitBootServices service. > + * Functions tagged with these keywords are resident (available at boot time and > + * at runtime) > + */ > + > +#define __ffa_runtime_data __efi_runtime_data > +#define __ffa_runtime __efi_runtime > + > +#else > + > +/* > + * The FF-A driver is independent from EFI > + */ > + > +#define __ffa_runtime_data > +#define __ffa_runtime > + > +#endif > + > +/** > + * 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)(const char *uuid_str, > + u32 *parts_size, struct ffa_partition_info *buffer); > + int (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg); > + int (*rxtx_unmap)(void); > +}; > + > +/** > + * The device driver and the Uclass driver public functions > + */ > + > +/** > + * ffa_bus_ops_get - driver operations getter > + */ > +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 > + */ > +int ffa_bus_discover(void); > + > +#if CONFIG_IS_ENABLED(ARM_FFA_EFI_RUNTIME_MODE) > + > +/** > + * ffa_copy_runtime_data - copy the private data structure and the SPs data to the runtime area > + */ > +efi_status_t ffa_copy_runtime_data(void); > + > +#endif > + > +#endif > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h > index a432e43871..6eebbe9c7d 100644 > --- a/include/dm/uclass-id.h > +++ b/include/dm/uclass-id.h > @@ -55,6 +55,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_FUZZING_ENGINE, /* Fuzzing engine */ > UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */ > diff --git a/include/uuid.h b/include/uuid.h > index 4a4883d3b5..789f8e0f15 100644 > --- a/include/uuid.h > +++ b/include/uuid.h > @@ -44,4 +44,12 @@ 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); > + > +#ifdef CONFIG_ARM_FFA_TRANSPORT > +/** > + * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer > + */ > +int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin); > +#endif > + > #endif > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c > index 4da64b5d29..e02bb445f5 100644 > --- a/lib/efi_loader/efi_boottime.c > +++ b/lib/efi_loader/efi_boottime.c > @@ -23,6 +23,10 @@ > #include > #include > > +#if defined(CONFIG_ARM_FFA_TRANSPORT) > +#include > +#endif > + > DECLARE_GLOBAL_DATA_PTR; > > /* Task priority level */ > @@ -2113,6 +2117,10 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, > struct efi_event *evt, *next_event; > efi_status_t ret = EFI_SUCCESS; > > +#if defined(CONFIG_ARM_FFA_TRANSPORT) > + int ffa_ret; > +#endif > + > EFI_ENTRY("%p, %zx", image_handle, map_key); > > /* Check that the caller has read the current memory map */ > @@ -2173,6 +2181,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, > dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); > } > > +#if defined(CONFIG_ARM_FFA_TRANSPORT) > + /* unmap FF-A RX/TX buffers */ > + ffa_ret = ffa_bus_ops_get()->rxtx_unmap(); > + if (ffa_ret) > + debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n"); > + else > + debug("[efi_boottime][INFO]: FF-A RX/TX buffers unmapped\n"); > +#endif > + > /* Patch out unsupported runtime function */ > efi_runtime_detach(); > > diff --git a/lib/uuid.c b/lib/uuid.c > index 284f8113ff..50b3e61d59 100644 > --- a/lib/uuid.c > +++ b/lib/uuid.c > @@ -1,6 +1,7 @@ > // SPDX-License-Identifier: GPL-2.0+ > /* > * Copyright 2011 Calxeda, Inc. > + * Copyright 2022 ARM Limited > */ > > #include > @@ -342,6 +343,70 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin, > return 0; > } > > +#ifdef CONFIG_ARM_FFA_TRANSPORT > +/** > + * ffa_uuid_str_to_bin - Converts a big endian UUID string to a little endian buffer > + * @uuid_str: UUID string in big endian format (36 bytes wide + '/0') > + * @uuid_bin: preallocated 16 bytes UUID buffer in little endian format > + * > + * UUID string is 36 characters (36 bytes): > + * > + * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx > + * be be be be be > + * > + * where x is a hexadecimal character. Fields are separated by '-'s. > + * When converting to a binary UUID, these endianness rules apply: > + * be: means the field in the string is considered a big endian hex number > + * and should be converted to little endian binary format > + * > + * Return: > + * > + * uuid_bin filled with little endian UUID data > + * On success 0 is returned. Otherwise, failure code. > + */ > +int ffa_uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin) > +{ > + u16 tmp16 = 0; > + u32 tmp32 = 0; > + u64 tmp64 = 0; > + > + if (!uuid_str_valid(uuid_str) || !uuid_bin) > + return -EINVAL; > + > + /* > + * reverse bytes from big to little endian > + */ > + tmp32 = simple_strtoul(uuid_str, NULL, 16); > + memcpy(uuid_bin, &tmp32, 4); > + > + /* > + * reverse bytes from big to little endian > + */ > + tmp16 = simple_strtoul(uuid_str + 9, NULL, 16); > + memcpy(uuid_bin + 4, &tmp16, 2); > + > + /* > + * reverse bytes from big to little endian > + */ > + tmp16 = simple_strtoul(uuid_str + 14, NULL, 16); > + memcpy(uuid_bin + 6, &tmp16, 2); > + > + /* > + * reverse bytes from big to little endian > + */ > + tmp16 = simple_strtoul(uuid_str + 19, NULL, 16); > + memcpy(uuid_bin + 8, &tmp16, 2); > + > + /* > + * reverse bytes from big to little endian > + */ > + tmp64 = simple_strtoull(uuid_str + 24, NULL, 16); > + memcpy(uuid_bin + 10, (char *)&tmp64, 6); > + > + return 0; > +} > +#endif > + > /* > * uuid_bin_to_str() - convert big endian binary data to string UUID or GUID. > * > -- > 2.17.1 >