[PATCH v1 36/54] restart: allow drivers to register runtime restart handler

Ahmad Fatoum a.fatoum at pengutronix.de
Thu Dec 18 02:37:56 PST 2025


From: Ahmad Fatoum <a.fatoum at barebox.org>

A runtime restart handler needs to be usable from within the barebox EFI
runtime services, even when everything else in barebox has been
discarded and barebox no longer has exclusive access to peripherals.

This driver allows existing drivers for boot time barebox to probe as
normal and optionally register a runtime restart handler, which is
suitable for being called from within EFI runtime code.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/restart.c  | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 include/restart.h |  3 +++
 2 files changed, 49 insertions(+)

diff --git a/common/restart.c b/common/restart.c
index d0ceeab7acd0..391d7bd3773c 100644
--- a/common/restart.c
+++ b/common/restart.c
@@ -7,11 +7,42 @@
 #include <common.h>
 #include <restart.h>
 #include <malloc.h>
+#include <asm/sections.h>
+#include <efi/types.h>
 #include <of.h>
 
 static LIST_HEAD(restart_handler_list);
 static unsigned resetidx;
 
+static __efi_runtime_data void (*rt_restart)(unsigned long flags);
+static int rt_restart_prio = INT_MIN;
+static __efi_runtime_data void (*rt_restart_warm)(unsigned long flags);
+static int rt_restart_warm_prio = INT_MIN;
+
+static void rt_restart_handler_register(struct restart_handler *handler)
+{
+	if (!IS_ENABLED(CONFIG_EFI_RUNTIME))
+		return;
+	if (!handler->rt_restart)
+		return;
+	if (!in_barebox_efi_runtime((ulong)handler->rt_restart)) {
+		/* Check if __efi_runtime attribute is missing */
+		pr_warn("handler outside EFI runtime section\n");
+		return;
+	}
+
+	if (handler->priority > rt_restart_prio) {
+		rt_restart = handler->rt_restart;
+		rt_restart_prio = handler->priority;
+	}
+
+	if (handler->priority > rt_restart_warm_prio &&
+	    handler->flags & RESTART_WARM) {
+		rt_restart_warm = handler->rt_restart;
+		rt_restart_warm_prio = handler->priority;
+	}
+}
+
 /**
  * restart_handler_register() - register a handler for restarting the system
  * @rst:	The handler struct
@@ -35,6 +66,8 @@ int restart_handler_register(struct restart_handler *rst)
 			rst->flags |= RESTART_WARM;
 	}
 
+	rt_restart_handler_register(rst);
+
 	list_add_tail(&rst->list, &restart_handler_list);
 
 	pr_debug("registering restart handler \"%s\" with priority %d\n",
@@ -100,6 +133,19 @@ struct restart_handler *restart_handler_get_by_name(const char *name, int flags)
 	return rst;
 }
 
+/**
+ * rt_restart_machine() - reset the machine from a runtime service
+ */
+void __noreturn __efi_runtime rt_restart_machine(unsigned long flags)
+{
+	if ((flags & RESTART_WARM) && rt_restart_warm)
+		rt_restart_warm(flags);
+	if (rt_restart)
+		rt_restart(flags);
+
+	__hang();
+}
+
 /**
  * restart_machine() - reset the whole system
  */
diff --git a/include/restart.h b/include/restart.h
index 5414fc1fcb69..cafddc14c656 100644
--- a/include/restart.h
+++ b/include/restart.h
@@ -5,11 +5,13 @@
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <linux/bitops.h>
+#include <efi/types.h>
 
 struct device_node;
 
 void restart_handlers_print(void);
 #define RESTART_WARM			BIT(0)
+void __noreturn __efi_runtime rt_restart_machine(unsigned long flags);
 void __noreturn restart_machine(unsigned long restart_flags);
 struct restart_handler *restart_handler_get_by_name(const char *name, int flags);
 
@@ -17,6 +19,7 @@ struct device_node;
 
 struct restart_handler {
 	void (*restart)(struct restart_handler *, unsigned long);
+	void (*rt_restart)(unsigned long);
 	int priority;
 	int flags;
 	struct device_node *of_node;
-- 
2.47.3




More information about the barebox mailing list