console: Implement pre-console buffer

Allow redirection of console output prior to console initialisation to a
temporary buffer.

To enable this functionality, the board (or arch) must define:
 - CONFIG_PRE_CONSOLE_BUFFER - Enable pre-console buffer
 - CONFIG_PRE_CON_BUF_ADDR - Base address of pre-console buffer
 - CONFIG_PRE_CON_BUF_SZ - Size of pre-console buffer (in bytes)

The pre-console buffer will buffer the last CONFIG_PRE_CON_BUF_SZ bytes
Any earlier characters are silently dropped.
diff --git a/common/console.c b/common/console.c
index b23d933..f17875e 100644
--- a/common/console.c
+++ b/common/console.c
@@ -329,6 +329,39 @@
 	return serial_tstc();
 }
 
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
+#define CIRC_BUF_IDX(idx) ((idx) % (unsigned long)CONFIG_PRE_CON_BUF_SZ)
+
+static void pre_console_putc(const char c)
+{
+	char *buffer = (char *)CONFIG_PRE_CON_BUF_ADDR;
+
+	buffer[CIRC_BUF_IDX(gd->precon_buf_idx++)] = c;
+}
+
+static void pre_console_puts(const char *s)
+{
+	while (*s)
+		pre_console_putc(*s++);
+}
+
+static void print_pre_console_buffer(void)
+{
+	unsigned long i = 0;
+	char *buffer = (char *)CONFIG_PRE_CON_BUF_ADDR;
+
+	if (gd->precon_buf_idx > CONFIG_PRE_CON_BUF_SZ)
+		i = gd->precon_buf_idx - CONFIG_PRE_CON_BUF_SZ;
+
+	while (i < gd->precon_buf_idx)
+		putc(buffer[CIRC_BUF_IDX(i++)]);
+}
+#else
+static inline void pre_console_putc(const char c) {}
+static inline void pre_console_puts(const char *s) {}
+static inline void print_pre_console_buffer(void) {}
+#endif
+
 void putc(const char c)
 {
 #ifdef CONFIG_SILENT_CONSOLE
@@ -342,7 +375,7 @@
 #endif
 
 	if (!gd->have_console)
-		return;
+		return pre_console_putc(c);
 
 	if (gd->flags & GD_FLG_DEVINIT) {
 		/* Send to the standard output */
@@ -366,7 +399,7 @@
 #endif
 
 	if (!gd->have_console)
-		return;
+		return pre_console_puts(s);
 
 	if (gd->flags & GD_FLG_DEVINIT) {
 		/* Send to the standard output */
@@ -383,8 +416,10 @@
 	uint i;
 	char printbuffer[CONFIG_SYS_PBSIZE];
 
+#ifndef CONFIG_PRE_CONSOLE_BUFFER
 	if (!gd->have_console)
 		return 0;
+#endif
 
 	va_start(args, fmt);
 
@@ -404,8 +439,10 @@
 	uint i;
 	char printbuffer[CONFIG_SYS_PBSIZE];
 
+#ifndef CONFIG_PRE_CONSOLE_BUFFER
 	if (!gd->have_console)
 		return 0;
+#endif
 
 	/* For this to work, printbuffer must be larger than
 	 * anything we ever want to print.
@@ -547,6 +584,8 @@
 		gd->flags |= GD_FLG_SILENT;
 #endif
 
+	print_pre_console_buffer();
+
 	return 0;
 }