[U-Boot] [PATCH 01/21] Define new system_restart() and emergency_restart()

Kyle Moffett Kyle.D.Moffett at boeing.com
Mon Mar 7 18:37:22 CET 2011


In preparation for making system restart use a generic set of hooks for
boards and architectures, we define some wrappers and weak stubs.

The new wrapper functions are:
  system_restart()     -  Normal system reboot (IE: user request)
  emergency_restart()  -  Critical error response (IE: panic(), etc)

During the process of converting all architectures to use the new hooks,
the system_restart() and emergency_restart() code will fall back to call
the existing do_reset() function.

The handler for the "reset" shell command is now do_generic_reset(),
which is a trivial wrapper around system_restart().

The new hooks (for architecture and board-support code to define) are:
  __arch_emergency_restart()
  __arch_restart()
  __board_emergency_restart()
  __board_restart()

By default the __(arch|board)_emergency_restart() functions just call
the corresponding __(arch|board)_restart() hook.  This works for all
hardware platforms which have a properly defined hardware reset
capability.

Signed-off-by: Kyle Moffett <Kyle.D.Moffett at boeing.com>
Cc: Wolfgang Denk <wd at denx.de>
---
 api/api.c                 |    3 +-
 common/cmd_boot.c         |  128 ++++++++++++++++++++++++++++++++++++++++++++-
 common/cmd_bootm.c        |    8 +--
 common/hush.c             |    2 +-
 common/main.c             |    2 +-
 examples/api/libgenwrap.c |    5 +-
 include/_exports.h        |    2 +-
 include/command.h         |   13 +++++
 lib/vsprintf.c            |    2 +-
 9 files changed, 152 insertions(+), 13 deletions(-)

diff --git a/api/api.c b/api/api.c
index 853f010..b65fabd 100644
--- a/api/api.c
+++ b/api/api.c
@@ -131,7 +131,8 @@ static int API_puts(va_list ap)
  */
 static int API_reset(va_list ap)
 {
-	do_reset(NULL, 0, 0, NULL);
+	if (system_restart())
+		return API_ENODEV;
 
 	/* NOT REACHED */
 	return 0;
diff --git a/common/cmd_boot.c b/common/cmd_boot.c
index 7b603d3..c0f26fc 100644
--- a/common/cmd_boot.c
+++ b/common/cmd_boot.c
@@ -58,6 +58,132 @@ int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	return rcode;
 }
 
+/*
+ * emergency_restart()  -  Restart function to call from panic(), etc.
+ *
+ * This may be called from any context when something has gone terribly wrong
+ * and the system needs a best-effort reboot.
+ *
+ * This function will never return.
+ */
+__attribute__((__noreturn__))
+void emergency_restart(void)
+{
+	__board_emergency_restart();
+	__arch_emergency_restart();
+
+	/* Fallback to the old do_reset() until everything is converted. */
+	do_reset(NULL, 0, 0, NULL);
+
+	printf("EMERGENCY RESTART: All attempts to reboot failed!");
+	hang();
+}
+
+/*
+ * Architecture/board-specific emergency-restart hooks.
+ *
+ * These hooks default to the same as the normal restart hooks.
+ *
+ * WARNING: If your platform's "restart" hooks are not a "safe" then you
+ * must redefine these functions in your port as empty stubs.
+ *
+ * Specifically, the following assumptions must be true for these hooks:
+ *   (1) Safe to call from any context (interrupts, etc).
+ *   (2) Must use a hardware mechanism to reset *ALL* system state.
+ *   (3) They must not be interruptible (EG: with Ctrl-C).
+ */
+__attribute__((__weak__))
+void __board_emergency_restart(void)
+{
+	__board_restart();
+}
+
+__attribute__((__weak__))
+void __arch_emergency_restart(void)
+{
+	__arch_restart();
+}
+
+/*
+ * This MUST be called from normal interrupts-on context.  If it requires
+ * extended interaction with external hardware it SHOULD react to Ctrl-C.
+ *
+ * If this function fails to guarantee a clean reboot or receives a Ctrl-C
+ * keystroke it SHOULD return with an error (-1).
+ */
+int system_restart(void)
+{
+	int err;
+
+	/*
+	 * Print a nice message and wait a bit to make sure it goes out the
+	 * console properly.
+	 */
+	printf ("Restarting...\n");
+	udelay(50000);
+
+	/* First let the board code try to reboot */
+	err = __board_restart();
+	if (err)
+		goto failed;
+
+	/* Now call into the architecture-specific code */
+	err = __arch_restart();
+	if (err)
+		goto failed;
+
+	/* Fallback to the old do_reset() until everything is converted. */
+	err = do_reset(NULL, 0, 0, NULL);
+
+failed:
+	printf("*** SYSTEM RESTART FAILED ***\n");
+	return err;
+}
+
+/*
+ * Architecture/board-specific restart hooks.
+ *
+ * If your implementation of these functions does not meet the requirements
+ * for the emergency_restart() hooks described above then you MUST separately
+ * implement those hooks.
+ */
+__attribute__((__weak__))
+int __board_restart(void)
+{
+	/* Fallthrough to architecture-specific code */
+	return 0;
+}
+
+__attribute__((__weak__))
+int __arch_restart(void)
+{
+	/* Fallthrough to legacy do_reset() code */
+	return 0;
+}
+
+/*
+ * Generic reset command implementation
+ *
+ * This is what you get when you type "reset" at the command line.
+ */
+int do_generic_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	return system_restart();
+}
+
+/*
+ * Empty legacy "do_reset" stub.
+ *
+ * This allows a platform using the new __board_restart() and
+ * __arch_restart() hooks to completely omit the old do_reset() function.
+ */
+int do_reset_stub(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	return 0;
+}
+__attribute__((__weak__,__alias__("do_reset_stub")))
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+
 /* -------------------------------------------------------------------- */
 
 U_BOOT_CMD(
@@ -68,7 +194,7 @@ U_BOOT_CMD(
 );
 
 U_BOOT_CMD(
-	reset, 1, 0,	do_reset,
+	reset, 1, 0,	do_generic_reset,
 	"Perform RESET of the CPU",
 	""
 );
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 18019d6..60e4983 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -645,7 +645,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	if (ret < 0) {
 		if (ret == BOOTM_ERR_RESET)
-			do_reset (cmdtp, flag, argc, argv);
+			emergency_restart();
 		if (ret == BOOTM_ERR_OVERLAP) {
 			if (images.legacy_hdr_valid) {
 				if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI)
@@ -655,7 +655,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 				puts ("ERROR: new format image overwritten - "
 					"must RESET the board to recover\n");
 				show_boot_progress (-113);
-				do_reset (cmdtp, flag, argc, argv);
+				emergency_restart();
 			}
 		}
 		if (ret == BOOTM_ERR_UNIMPLEMENTED) {
@@ -702,9 +702,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #ifdef DEBUG
 	puts ("\n## Control returned to monitor - resetting...\n");
 #endif
-	do_reset (cmdtp, flag, argc, argv);
-
-	return 1;
+	emergency_restart();
 }
 
 /**
diff --git a/common/hush.c b/common/hush.c
index 8021a68..f9e57c9 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -1036,7 +1036,7 @@ static void get_user_input(struct in_str *i)
 	if (n == -2) {
 	  puts("\nTimeout waiting for command\n");
 #  ifdef CONFIG_RESET_TO_RETRY
-	  do_reset(NULL, 0, 0, NULL);
+	  system_restart();
 #  else
 #	error "This currently only works with CONFIG_RESET_TO_RETRY enabled"
 #  endif
diff --git a/common/main.c b/common/main.c
index dcbacc9..abf77a5 100644
--- a/common/main.c
+++ b/common/main.c
@@ -450,7 +450,7 @@ void main_loop (void)
 			puts ("\nTimed out waiting for command\n");
 # ifdef CONFIG_RESET_TO_RETRY
 			/* Reinit board to run initialization code again */
-			do_reset (NULL, 0, 0, NULL);
+			system_restart();
 # else
 			return;		/* retry autoboot */
 # endif
diff --git a/examples/api/libgenwrap.c b/examples/api/libgenwrap.c
index 873cf34..31bfcf5 100644
--- a/examples/api/libgenwrap.c
+++ b/examples/api/libgenwrap.c
@@ -81,9 +81,10 @@ void __udelay(unsigned long usec)
 	ub_udelay(usec);
 }
 
-int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int system_restart(void)
 {
-	ub_reset();
+	if (ub_reset())
+		return -1;
 	return 0;
 }
 
diff --git a/include/_exports.h b/include/_exports.h
index d89b65b..3d3e511 100644
--- a/include/_exports.h
+++ b/include/_exports.h
@@ -15,7 +15,7 @@ EXPORT_FUNC(free)
 EXPORT_FUNC(udelay)
 EXPORT_FUNC(get_timer)
 EXPORT_FUNC(vprintf)
-EXPORT_FUNC(do_reset)
+EXPORT_FUNC(system_restart)
 EXPORT_FUNC(getenv)
 EXPORT_FUNC(setenv)
 EXPORT_FUNC(simple_strtoul)
diff --git a/include/command.h b/include/command.h
index 8310fe5..ad8c915 100644
--- a/include/command.h
+++ b/include/command.h
@@ -101,6 +101,19 @@ extern int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 extern int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 
+/* Generic system restart functions */
+__attribute__((__noreturn__))
+void emergency_restart(void);
+int system_restart(void);
+
+/* Architecture/board-specific emergency-restart hooks. */
+void __board_emergency_restart(void);
+void __arch_emergency_restart(void);
+
+/* Architecture/board-specific restart hooks. */
+int __board_restart(void);
+int __arch_restart(void);
+
 #endif	/* __ASSEMBLY__ */
 
 /*
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 61e6f0d..295b60b 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -674,6 +674,6 @@ void panic(const char *fmt, ...)
 	hang();
 #else
 	udelay (100000);	/* allow messages to go out */
-	do_reset (NULL, 0, 0, NULL);
+	emergency_restart();
 #endif
 }
-- 
1.7.2.3



More information about the U-Boot mailing list