[PATCH v2 03/11] efi_loader: add FF-A runtime support in EFI variable TEE driver

Ilias Apalodimas ilias.apalodimas at linaro.org
Fri Jun 5 12:46:56 CEST 2026


Hi Harsiman

[...]

> +/**
> + * ffa_map_sp_event() - Map MM SP response to errno
> + * @sp_event_ret: MM SP return code from MM SP notification
> + *
> + * Convert the MM SP return code into a standard U-Boot errno. This helper
> + * is marked __efi_runtime so it can be shared by both the boot and runtime
> + * FF-A notification paths.
> + *
> + * Return: 0 on success, negative errno on failure
> + */
> +static int __efi_runtime ffa_map_sp_event(int sp_event_ret)
> +{
> +       int idx = -sp_event_ret;
> +
> +       if (sp_event_ret == MM_SUCCESS)
> +               return 0;
> +       if (idx > 0 && idx < (int)ARRAY_SIZE(mm_sp_errmap) &&
> +           mm_sp_errmap[idx])
> +               return mm_sp_errmap[idx];
> +       return -EACCES;
> +}
> +
>  /**
>   * ffa_notify_mm_sp() - Announce there is data in the shared buffer
>   *
> @@ -177,52 +225,36 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize)
>   * This is a blocking call during which trusted world has exclusive access
>   * to the MM shared buffer.
>   *
> - * Return:
> - *
> - * 0 on success
> + * Return: 0 on success
>   */
> -static int ffa_notify_mm_sp(void)
> +static int __efi_runtime ffa_notify_mm_sp(void)
>  {
>         struct ffa_send_direct_data msg = {0};
>         int ret;
>         int sp_event_ret;
> -       struct udevice *dev;
> +       bool at_runtime = efi_at_runtime();
>
> -       ret = uclass_first_device_err(UCLASS_FFA, &dev);
> -       if (ret) {
> -               log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");
> -               return ret;
> -       }
> +       msg.data0 = CONFIG_FFA_SHARED_MM_BUF_OFFSET;
> +
> +       if (at_runtime) {
> +               ret = ffa_sync_send_receive_runtime(mm_sp_id, &msg, 1);
> +       } else {
> +               struct udevice *dev;
>
> -       msg.data0 = CONFIG_FFA_SHARED_MM_BUF_OFFSET; /* x3 */
> +               ret = uclass_first_device_err(UCLASS_FFA, &dev);
> +               if (ret) {
> +                       log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n");

This will crash at runtime, we don't have access to log_XXX.
Please go through the entire patchset and make sure you aren't calling
core functions that haven't been marked as such for v3
Thre functions that do make sense can be converted to __efit_runtime.
log_XXXX is not one of them though.

> +                       return ret;
> +               }
>
> -       ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
> +               ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1);
> +       }
>         if (ret)
>                 return ret;
>
> -       sp_event_ret = msg.data0; /* x3 */
> -
> -       switch (sp_event_ret) {
> -       case MM_SUCCESS:
> -               ret = 0;
> -               break;
> -       case MM_NOT_SUPPORTED:
> -               ret = -EINVAL;
> -               break;
> -       case MM_INVALID_PARAMETER:
> -               ret = -EPERM;
> -               break;
> -       case MM_DENIED:
> -               ret = -EACCES;
> -               break;
> -       case MM_NO_MEMORY:
> -               ret = -EBUSY;
> -               break;
> -       default:
> -               ret = -EACCES;
> -       }
> +       sp_event_ret = msg.data0;
>
> -       return ret;
> +       return ffa_map_sp_event(sp_event_ret);
>  }
>
>  /**
> @@ -266,36 +298,41 @@ static int ffa_discover_mm_sp_id(void)
>  }
>
>  /**
> - * ffa_mm_communicate() - Exchange EFI services data with  the MM partition using FF-A
> + * ffa_mm_communicate() - Exchange EFI services data with the MM partition using FF-A
>   * @comm_buf:          locally allocated communication buffer used for rx/tx
> - * @dsize:                             communication buffer size
> + * @comm_buf_size:     communication buffer size
>   *
>   * Issue a door bell event to notify the MM partition (SP) running in OP-TEE
>   * that there is data to read from the shared buffer.
>   * Communication with the MM SP is performed using FF-A transport.
>   * On the event, MM SP can read the data from the buffer and
>   * update the MM shared buffer with response data.
> - * The response data is copied back to the communication buffer.
> - *
> - * Return:
> + * The response data is copied back to the communication buffer during the
> + * boot phase. At runtime, the communication buffer is already the FF-A
> + * shared buffer and is updated in place.
>   *
> - * EFI status code
> + * Return: EFI status code
>   */
> -static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
> +static efi_status_t __efi_runtime ffa_mm_communicate(void *comm_buf,
> +                                                    ulong comm_buf_size)
>  {
>         ulong tx_data_size;
>         int ffa_ret;
>         efi_status_t efi_ret;
>         struct efi_mm_communicate_header *mm_hdr;
> -       void *virt_shared_buf;
> +       u8 *shared_buf;
> +       bool at_runtime = efi_at_runtime();
>
>         if (!comm_buf)
>                 return EFI_INVALID_PARAMETER;
>
> -       /* Discover MM partition ID at boot time */
> -       if (!mm_sp_id && ffa_discover_mm_sp_id()) {
> -               log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
> -               return EFI_UNSUPPORTED;
> +       if (!mm_sp_id) {
> +               if (at_runtime)
> +                       return EFI_UNSUPPORTED;
> +               if (ffa_discover_mm_sp_id()) {
> +                       log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n");
> +                       return EFI_UNSUPPORTED;
> +               }
>         }
>
>         mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> @@ -304,30 +341,61 @@ static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
>         if (comm_buf_size != tx_data_size || tx_data_size > CONFIG_FFA_SHARED_MM_BUF_SIZE)
>                 return EFI_INVALID_PARAMETER;
>
> -       /* Copy the data to the shared buffer */
> -
> -       virt_shared_buf = map_sysmem((phys_addr_t)CONFIG_FFA_SHARED_MM_BUF_ADDR, 0);
> -       memcpy(virt_shared_buf, comm_buf, tx_data_size);
> +       if (at_runtime) {
> +               shared_buf = comm_buf;
> +       } else {
> +               /* Copy the data to the shared buffer */
> +               shared_buf = map_sysmem((phys_addr_t)CONFIG_FFA_SHARED_MM_BUF_ADDR, 0);
> +               memcpy(shared_buf, comm_buf, tx_data_size);
> +       }

Does the shared_buf live in the same memory space for linux ? How is
that communicated to the OS?

[...]


Thanks
/Ilias


More information about the U-Boot mailing list