Hi Harsimran
>
> /**
> - * setup_mm_hdr() - Allocate a buffer for StandAloneMM and initialize the
> - * header data.
> + * get_comm_buf() - Obtain a communication buffer for MM/FF-A exchange
> + * @payload_size: size of the payload that will be appended to the
> + * MM communication header
> + *
> + * This helper returns a buffer suitable for constructing an
> + * EFI_MM_COMMUNICATE message. During the boot phase a new buffer is
> + * dynamically allocated. After ExitBootServices(), dynamic
> + * allocation is no longer permitted, and all runtime communication must
> + * use the statically reserved FF-A shared buffer.
> + *
> + * The caller owns the returned buffer only during the boot phase and
> + * must release it with free(). During the runtime phase, the returned
> + * pointer aliases the static FF-A shared buffer and must not be freed.
> + *
> + * Return:
> + * Pointer to a valid communication buffer on success.
> + * NULL if no suitable communication buffer is available.
> + */
> +static __efi_runtime u8 *get_comm_buf(efi_uintn_t payload_size)
> +{
> + efi_uintn_t comm_buf_size;
> + u8 *comm_buf;
> +
> + comm_buf_size = MM_COMMUNICATE_HEADER_SIZE +
> + MM_VARIABLE_COMMUNICATE_SIZE +
> + payload_size;
> +
> + /*
> + * After ExitBootServices(), dynamic allocation is no longer permitted.
> + * Use the predefined FF-A shared buffer at runtime; otherwise allocate
> + * a fresh buffer during the boot phase.
> + */
> + if (efi_at_runtime()) {
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
> + if (IS_ENABLED(CONFIG_ARM_FFA_RT_MODE)) {
> + if (comm_buf_size > CONFIG_FFA_SHARED_MM_BUF_SIZE)
> + return NULL;
> + comm_buf = ffa_shared_buf;
> + if (!comm_buf)
> + return NULL;
> + efi_memset_runtime(comm_buf, 0, comm_buf_size);
> + } else {
> + return NULL;
This is problematic for the existing use case. With the changes in the later
patches
that swap all runtime call unconditionally every call to setup_mm_hdr() will
return
EFI_OUT_OF_RESOURCES and none of the runtime services will work without FF-A.
There's nothing elegant we can do about this .We either Let the fucntions from
efi_var_common.c
deal with the runtime part (which I think I prefer), or we define a similar
runtime
available buffer for comm_buf.
> + }
> +#else
> + return NULL;
> +#endif
> + } else {
> + comm_buf = calloc(1, comm_buf_size);
> + if (!comm_buf)
> + return NULL;
> + }
> + return comm_buf;
> +}
> +
> +/**
> +static __efi_runtime u8 *setup_mm_hdr(void **dptr, efi_uintn_t payload_size,
> + efi_uintn_t func, efi_status_t *ret)
> {
> - const efi_guid_t mm_var_guid = EFI_MM_VARIABLE_GUID;
> + static const __efi_runtime_rodata efi_guid_t mm_var_guid =
> + EFI_MM_VARIABLE_GUID;
> struct efi_mm_communicate_header *mm_hdr;
> struct smm_variable_communicate_header *var_hdr;
> u8 *comm_buf;
> @@ -555,16 +615,15 @@ static u8 *setup_mm_hdr(void **dptr, efi_uintn_t
> payload_size,
> return NULL;
> }
>
> - comm_buf = calloc(1, MM_COMMUNICATE_HEADER_SIZE +
> - MM_VARIABLE_COMMUNICATE_SIZE +
> - payload_size);
> + comm_buf = get_comm_buf(payload_size);
> if (!comm_buf) {
> *ret = EFI_OUT_OF_RESOURCES;
> return NULL;
> }
>
> mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
> - guidcpy(&mm_hdr->header_guid, &mm_var_guid);
> + efi_memcpy_runtime(&mm_hdr->header_guid, &mm_var_guid,
> + sizeof(mm_hdr->header_guid));
> mm_hdr->message_len = MM_VARIABLE_COMMUNICATE_SIZE + payload_size;
>
> var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
> @@ -1077,6 +1136,20 @@ void efi_variables_boot_exit_notify(void)
> ebs_called = true;
> }
>
> +/**
> + * ffa_shared_buf_notify_virtual_address_map() - SetVirtualAddressMap
> callback
> + *
> + * @event: callback event
> + * @context: callback context
> + */
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) &&
> IS_ENABLED(CONFIG_ARM_FFA_RT_MODE)
> +static void EFIAPI __efi_runtime
> +ffa_shared_buf_notify_virtual_address_map(struct efi_event *event, void
> *context)
> +{
> + efi_convert_pointer(0, (void **)&ffa_shared_buf);
> +}
> +#endif
> +
> /**
> * efi_init_variables() - initialize variable services
> *
> @@ -1085,6 +1158,9 @@ void efi_variables_boot_exit_notify(void)
> efi_status_t efi_init_variables(void)
> {
> efi_status_t ret;
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) &&
> IS_ENABLED(CONFIG_ARM_FFA_RT_MODE)
> + struct efi_event *event;
> +#endif
>
> /* Create a cached copy of the variables that will be enabled on
> ExitBootServices() */
> ret = efi_var_mem_init();
> @@ -1103,5 +1179,37 @@ efi_status_t efi_init_variables(void)
> if (ret != EFI_SUCCESS)
> return ret;
>
> +#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) &&
> IS_ENABLED(CONFIG_ARM_FFA_RT_MODE)
> + if (IS_ENABLED(CONFIG_ARM_FFA_RT_MODE)) {
> + /*
> + * The FF-A shared buffer is accessed by EFI runtime services,
> so
> + * keep the resident pointer convertible across
> + * SetVirtualAddressMap() and mark the region as runtime memory.
> + *
> + * CONFIG_FFA_SHARED_MM_BUF_ADDR is expected to be EFI-page
> aligned.
> + */
> + BUILD_BUG_ON(CONFIG_FFA_SHARED_MM_BUF_ADDR & EFI_PAGE_MASK);
> + ffa_shared_buf = (void *)CONFIG_FFA_SHARED_MM_BUF_ADDR;
> + ret = efi_create_event(EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
> + TPL_CALLBACK,
> +
> ffa_shared_buf_notify_virtual_address_map,
> + NULL, NULL, &event);
> + if (ret != EFI_SUCCESS)
> + return ret;
> + ret = efi_add_memory_map(CONFIG_FFA_SHARED_MM_BUF_ADDR,
> + CONFIG_FFA_SHARED_MM_BUF_SIZE,
> + EFI_RUNTIME_SERVICES_DATA);
> + if (ret != EFI_SUCCESS) {
> + efi_close_event(event);
> + log_err("EFI: failed to add FF-A shared buffer to
> runtime map (%lu)\n",
> + ret);
> + return ret;
> + }
> + log_info("EFI: FF-A shared buffer runtime map: addr=0x%lx
> size=0x%lx\n",
> + (ulong)CONFIG_FFA_SHARED_MM_BUF_ADDR,
> + (ulong)CONFIG_FFA_SHARED_MM_BUF_SIZE);
> + }
> +#endif
> +
> return EFI_SUCCESS;
> }