[U-Boot] [PATCH 2/5] Add board_panic_no_console() to deal with early critical errors

Simon Glass sjg at chromium.org
Mon Mar 19 21:27:01 CET 2012

This patch adds support for console output in the event of a panic() before
the console is inited. The main purpose of this is to deal with a very early
panic() which would otherwise cause a silent hang.

A new board_pre_console_panic() function is added to the board API. If
provided by the board it will be called in the event of a panic before the
console is ready. This function should turn on all available UARTs and
output the string (plus a newline) if it possibly can.

Signed-off-by: Simon Glass <sjg at chromium.org>
 README           |   34 ++++++++++++++++++++++++++++++++++
 include/common.h |    8 ++++++++
 lib/vsprintf.c   |   25 +++++++++++++++++++++++--
 3 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/README b/README
index 84757a5..38ce52a 100644
--- a/README
+++ b/README
@@ -638,6 +638,40 @@ The following options need to be configured:
 		'Sane' compilers will generate smaller code if
 		CONFIG_PRE_CON_BUF_SZ is a power of 2
+- Pre-console panic():
+		Prior to the console being initialised, console output is
+		normally silently discarded. This can be annoying if a
+		panic() happens in this time. One reason for this might be
+		that you have CONFIG_OF_CONTROL defined but have not
+		provided a valid device tree for U-Boot. In general U-Boot's
+		console code cannot resolve this problem, since the console
+		has not been set up, and it may not be known which UART is
+		the console anyway (for example if this information is in
+		the device tree).
+		The solution is to define a function called
+		board_pre_console_panic() for your board, which alerts the
+		user however it can. Hopefuly this will involve displaying
+		a message on available UARTs, or perhaps at least flashing
+		an LED. The function should be very careful to only output
+		to UARTs that are known to be unused for peripheral
+		interfaces, and change GPIOs that will have no ill effect
+		on the board. That said, it is fine to do something
+		destructive that will prevent the board from continuing to
+		boot, since it isn't going to...
+		The function will need to output serial data directly,
+		since the console code is not functional yet. Note that if
+		the panic happens early enough, then it is possible that
+		board_init_f() (or even arch_cpu_init() on ARM) has not
+		been called yet. You should init all clocks, GPIOs, etc.
+		that are needed to get the string out. Baud rates will need
+		to default to something sensible.
+		If your function returns, then the normal panic processing
+		will occur (it will either hang or reset depending on
 - Safe printf() functions
 		Define CONFIG_SYS_VSNPRINTF to compile in safe versions of
 		the printf() functions. These are defined in
diff --git a/include/common.h b/include/common.h
index b588410..9db3a6a 100644
--- a/include/common.h
+++ b/include/common.h
@@ -285,6 +285,14 @@ extern ulong monitor_flash_len;
 int mac_read_from_eeprom(void);
 extern u8 _binary_dt_dtb_start[];	/* embedded device tree blob */
+ * Called during a panic() when no console is available. The board should do
+ * its best to get a message to the user any way it can. This function should
+ * return if it can, in which case the system will either hang or reset.
+ * See panic().
+ */
+void board_pre_console_panic(const char *str);
 /* common/flash.c */
 void flash_perror (int);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index e38a4b7..a478ff5ab 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -33,6 +33,9 @@ const char hex_asc[] = "0123456789abcdef";
 #define hex_asc_lo(x)   hex_asc[((x) & 0x0f)]
 #define hex_asc_hi(x)   hex_asc[((x) & 0xf0) >> 4]
 static inline char *pack_hex_byte(char *buf, u8 byte)
 	*buf++ = hex_asc_hi(byte);
@@ -777,13 +780,31 @@ int sprintf(char * buf, const char *fmt, ...)
 	return i;
+/* Provide a default function for when no console is available */
+static void __board_pre_console_panic(const char *msg)
+	/* Just return since we can't access the console */
+void board_pre_console_panic(const char *msg) __attribute__((weak,
+					alias("__board_pre_console_panic")));
 void panic(const char *fmt, ...)
+	char str[CONFIG_SYS_PBSIZE];
 	va_list	args;
 	va_start(args, fmt);
-	vprintf(fmt, args);
-	putc('\n');
+	vsnprintf(str, sizeof(str), fmt, args);
+	if (gd->have_console) {
+		puts(str);
+		putc('\n');
+	} else {
+		board_pre_console_panic(str);
+	}
 #if defined (CONFIG_PANIC_HANG)

More information about the U-Boot mailing list