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

Reply via email to