[PATCH v3 3/4] arm_ffa: introduce Arm FF-A low-level driver

Ilias Apalodimas ilias.apalodimas at linaro.org
Fri Aug 12 09:39:23 CEST 2022


Hi Abdellatif,

On Mon, 1 Aug 2022 at 20:21, Abdellatif El Khlifi
<abdellatif.elkhlifi at arm.com> 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 <abdellatif.elkhlifi at arm.com>
> + */
> +
> +#include "arm_ffa_prv.h"
> +#include <asm/global_data.h>
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/device-internal.h>
> +#include <dm/devres.h>
> +#include <dm/root.h>
> +#include <linux/errno.h>
> +#include <linux/sizes.h>
> +#include <log.h>
> +#include <malloc.h>
> +#include <string.h>
> +#include <uuid.h>
> +
> +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 <abdellatif.elkhlifi at arm.com>
> + */
> +
> +#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 <abdellatif.elkhlifi at arm.com>
> + */
> +
> +#ifndef __ARM_FFA_H
> +#define __ARM_FFA_H
> +
> +#include <linux/printk.h>
> +
> +/*
> + * 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 <efi_loader.h>
> +
> +/*
> + *  __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 <asm/setjmp.h>
>  #include <linux/libfdt_env.h>
>
> +#if defined(CONFIG_ARM_FFA_TRANSPORT)
> +#include <arm_ffa.h>
> +#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 <common.h>
> @@ -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
>


More information about the U-Boot mailing list