Register an ExitBootServices event after the FF-A bus has completed probe. The callback copies the boot-discovered runtime fields into resident storage and marks the FF-A runtime context ready. EFI runtime services can then use the runtime transport without depending on driver model state.
Reviewed-by: Simon Glass <[email protected]> Acked-by: Abdellatif El Khlifi <[email protected]> Signed-off-by: Harsimran Singh Tungal <[email protected]> --- drivers/firmware/arm-ffa/arm-ffa-runtime.c | 43 ++++++++++++++++++++++ drivers/firmware/arm-ffa/arm-ffa-uclass.c | 9 +++++ include/arm_ffa_runtime.h | 18 +++++++++ 3 files changed, 70 insertions(+) diff --git a/drivers/firmware/arm-ffa/arm-ffa-runtime.c b/drivers/firmware/arm-ffa/arm-ffa-runtime.c index d761ec9ee07..84c1a203d40 100644 --- a/drivers/firmware/arm-ffa/arm-ffa-runtime.c +++ b/drivers/firmware/arm-ffa/arm-ffa-runtime.c @@ -37,6 +37,49 @@ static const __ffa_runtime_data struct ffa_bus_ops_runtime ffa_ops_rt = { #define ffa_get_ops_runtime() (&ffa_ops_rt) #define ffa_get_priv_runtime() (&ffa_priv_rt) +#if IS_ENABLED(CONFIG_ARM_FFA_RT_MODE) +static void EFIAPI ffa_rt_exit_boot_services_notify(struct efi_event *event, + void *context) +{ + struct ffa_priv *priv = context; + + if (!priv) { + log_warning("FF-A: runtime data missing, keeping RT mode disabled\n"); + return; + } + + ffa_copy_runtime_priv(&priv->rt); + ffa_runtime_context_enable(); +} + +/** + * ffa_setup_efi_exit_boot_services_event() - register ExitBootServices event + * @priv: pointer to the FF-A private data + * + * Register an EFI event that enables the FF-A runtime context when + * ExitBootServices() is invoked. + * + * Return: 0 on success, -EPERM on failure to create the event. + */ +int ffa_setup_efi_exit_boot_services_event(struct ffa_priv *priv) +{ + efi_status_t efi_ret; + struct efi_event *evt = NULL; + + efi_ret = efi_create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK, + ffa_rt_exit_boot_services_notify, priv, + &efi_guid_event_group_exit_boot_services, + &evt); + if (efi_ret != EFI_SUCCESS) { + log_err("FF-A: cannot install ExitBootServices event %p, err (%lu)\n", + evt, efi_ret); + return -EPERM; + } + + return 0; +} +#endif + /** * ffa_copy_runtime_priv() - copy runtime data into resident storage * @priv: pointer to the runtime private data diff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c index 668c2156f8b..d21cc4cc35c 100644 --- a/drivers/firmware/arm-ffa/arm-ffa-uclass.c +++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c @@ -937,6 +937,7 @@ int ffa_rxtx_unmap(struct udevice *dev) static int ffa_do_probe(struct udevice *dev) { int ret; + struct ffa_priv *uc_priv = dev_get_uclass_priv(dev); ret = ffa_get_version_hdlr(dev); if (ret) @@ -960,6 +961,14 @@ static int ffa_do_probe(struct udevice *dev) return ret; } + if (IS_ENABLED(CONFIG_ARM_FFA_RT_MODE)) { + ret = ffa_setup_efi_exit_boot_services_event(uc_priv); + if (ret) { + ffa_unmap_rxtx_buffers_hdlr(dev); + return ret; + } + } + return 0; } diff --git a/include/arm_ffa_runtime.h b/include/arm_ffa_runtime.h index 77b528745e8..bfc4d387660 100644 --- a/include/arm_ffa_runtime.h +++ b/include/arm_ffa_runtime.h @@ -84,6 +84,24 @@ void ffa_runtime_context_reset(void); */ void ffa_copy_runtime_priv(const struct ffa_priv_runtime *priv); +/** + * ffa_setup_efi_exit_boot_services_event() - register ExitBootServices event + * @priv: pointer to the FF-A private data + * + * Register an EFI event that enables the FF-A runtime context when + * ExitBootServices() is invoked. + * + * Return: 0 on success, -EPERM on failure to create the event. + */ +#if IS_ENABLED(CONFIG_ARM_FFA_RT_MODE) +int ffa_setup_efi_exit_boot_services_event(struct ffa_priv *priv); +#else +static inline int ffa_setup_efi_exit_boot_services_event(struct ffa_priv *priv) +{ + return 0; +} +#endif + /** * ffa_runtime_context_ready() - Query FF-A runtime readiness * -- 2.34.1
