[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