[U-Boot] [PATCH V4] console: Implement pre-console buffer

Graeme Russ graeme.russ at gmail.com
Wed Aug 31 14:58:25 CEST 2011


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

To enable this functionality, the board configuration file 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.

Signed-off-by: Graeme Russ <graeme.russ at gmail.com>
---
Changes since V3
 - Fixed  blank subject caused by gap between the Cc: list and Date:

Changes since V2
 - Cast buffer size to unsigned long to help compilers produce tighter
   code
 - Use inline stub functions to reduce #ifdef clutter
 - Add documentation to README

Changes Since V1
 - Implemented circular buffer
 - Trivial code styl corrections

 README                                    |   14 +++++++++
 arch/arm/include/asm/global_data.h        |    3 ++
 arch/avr32/include/asm/global_data.h      |    3 ++
 arch/blackfin/include/asm/global_data.h   |    3 ++
 arch/m68k/include/asm/global_data.h       |    3 ++
 arch/microblaze/include/asm/global_data.h |    3 ++
 arch/mips/include/asm/global_data.h       |    3 ++
 arch/nios2/include/asm/global_data.h      |    3 ++
 arch/powerpc/include/asm/global_data.h    |    3 ++
 arch/sh/include/asm/global_data.h         |    3 ++
 arch/sparc/include/asm/global_data.h      |    3 ++
 arch/x86/include/asm/global_data.h        |    3 ++
 common/console.c                          |   43 +++++++++++++++++++++++++++-
 13 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/README b/README
index 0886987..170e67b 100644
--- a/README
+++ b/README
@@ -619,6 +619,20 @@ The following options need to be configured:
 		must be defined, to setup the maximum idle timeout for
 		the SMC.

+- Pre-Console Buffer:
+                Prior to the console being initialised (i.e. serial UART
+                initialised etc) all console output is silently discarded.
+                Defining CONFIG_PRE_CONSOLE_BUFFER will cause U-Boot to
+                buffer any console messages prior to the console being
+                initialised to a buffer of size CONFIG_PRE_CON_BUF_SZ
+                bytes located at CONFIG_PRE_CON_BUF_ADDR. The buffer is
+                a cicular buffer, so if more than CONFIG_PRE_CON_BUF_SZ
+                bytes are output before the console is  initialised, the
+                earlier bytes are discarded.
+
+                'Sane' compilers will generate smaller code if
+                CONFIG_PRE_CON_BUF_SZ is a power of 2
+
 - Boot Delay:	CONFIG_BOOTDELAY - in seconds
 		Delay before automatically booting the default image;
 		set to -1 to disable autoboot.
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index 4fc51fd..b85b7fe 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -38,6 +38,9 @@ typedef	struct	global_data {
 	unsigned long	flags;
 	unsigned long	baudrate;
 	unsigned long	have_console;	/* serial_init() was called */
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
+	unsigned long	precon_buf_idx;	/* Pre-Console buffer index */
+#endif
 	unsigned long	env_addr;	/* Address  of Environment struct */
 	unsigned long	env_valid;	/* Checksum of Environment valid? */
 	unsigned long	fb_base;	/* base address of frame buffer */
diff --git a/arch/avr32/include/asm/global_data.h b/arch/avr32/include/asm/global_data.h
index 4ef8fc5..5c654bd 100644
--- a/arch/avr32/include/asm/global_data.h
+++ b/arch/avr32/include/asm/global_data.h
@@ -38,6 +38,9 @@ typedef	struct	global_data {
 	unsigned long	baudrate;
 	unsigned long	stack_end;	/* highest stack address */
 	unsigned long	have_console;	/* serial_init() was called */
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
+	unsigned long	precon_buf_idx;	/* Pre-Console buffer index */
+#endif
 	unsigned long	reloc_off;	/* Relocation Offset */
 	unsigned long	env_addr;	/* Address of env struct */
 	unsigned long	env_valid;	/* Checksum of env valid? */
diff --git a/arch/blackfin/include/asm/global_data.h b/arch/blackfin/include/asm/global_data.h
index eba5e93..f7aa711 100644
--- a/arch/blackfin/include/asm/global_data.h
+++ b/arch/blackfin/include/asm/global_data.h
@@ -45,6 +45,9 @@ typedef struct global_data {
 	unsigned long board_type;
 	unsigned long baudrate;
 	unsigned long have_console;	/* serial_init() was called */
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
+	unsigned long	precon_buf_idx;	/* Pre-Console buffer index */
+#endif
 	phys_size_t ram_size;		/* RAM size */
 	unsigned long env_addr;	/* Address  of Environment struct */
 	unsigned long env_valid;	/* Checksum of Environment valid? */
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index fc486fd..0ba2b43 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -57,6 +57,9 @@ typedef	struct	global_data {
 	unsigned long	env_addr;	/* Address  of Environment struct	*/
 	unsigned long	env_valid;	/* Checksum of Environment valid?	*/
 	unsigned long	have_console;	/* serial_init() was called		*/
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
+	unsigned long	precon_buf_idx;	/* Pre-Console buffer index */
+#endif
 #if defined(CONFIG_LCD) || defined(CONFIG_VIDEO)
 	unsigned long	fb_base;	/* Base addr of framebuffer memory */
 #endif
diff --git a/arch/microblaze/include/asm/global_data.h b/arch/microblaze/include/asm/global_data.h
index 557ad27..6e8537c 100644
--- a/arch/microblaze/include/asm/global_data.h
+++ b/arch/microblaze/include/asm/global_data.h
@@ -39,6 +39,9 @@ typedef	struct	global_data {
 	unsigned long	flags;
 	unsigned long	baudrate;
 	unsigned long	have_console;	/* serial_init() was called */
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
+	unsigned long	precon_buf_idx;	/* Pre-Console buffer index */
+#endif
 	unsigned long	env_addr;	/* Address  of Environment struct */
 	unsigned long	env_valid;	/* Checksum of Environment valid? */
 	unsigned long	fb_base;	/* base address of frame buffer */
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
index 271a290..b193517 100644
--- a/arch/mips/include/asm/global_data.h
+++ b/arch/mips/include/asm/global_data.h
@@ -41,6 +41,9 @@ typedef	struct	global_data {
 	unsigned long	flags;
 	unsigned long	baudrate;
 	unsigned long	have_console;	/* serial_init() was called */
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
+	unsigned long	precon_buf_idx;	/* Pre-Console buffer index */
+#endif
 	phys_size_t	ram_size;	/* RAM size */
 	unsigned long	reloc_off;	/* Relocation Offset */
 	unsigned long	env_addr;	/* Address  of Environment struct */
diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
index 2c4a719..d9f0664 100644
--- a/arch/nios2/include/asm/global_data.h
+++ b/arch/nios2/include/asm/global_data.h
@@ -29,6 +29,9 @@ typedef	struct	global_data {
 	unsigned long	baudrate;
 	unsigned long	cpu_clk;	/* CPU clock in Hz!		*/
 	unsigned long	have_console;	/* serial_init() was called */
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
+	unsigned long	precon_buf_idx;	/* Pre-Console buffer index */
+#endif
 	phys_size_t	ram_size;	/* RAM size */
 	unsigned long	env_addr;	/* Address  of Environment struct */
 	unsigned long	env_valid;	/* Checksum of Environment valid */
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
index a33ca2f..7fcaf38 100644
--- a/arch/powerpc/include/asm/global_data.h
+++ b/arch/powerpc/include/asm/global_data.h
@@ -138,6 +138,9 @@ typedef	struct	global_data {
 	unsigned long	env_addr;	/* Address  of Environment struct	*/
 	unsigned long	env_valid;	/* Checksum of Environment valid?	*/
 	unsigned long	have_console;	/* serial_init() was called		*/
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
+	unsigned long	precon_buf_idx;	/* Pre-Console buffer index */
+#endif
 #if defined(CONFIG_SYS_ALLOC_DPRAM) || defined(CONFIG_CPM2)
 	unsigned int	dp_alloc_base;
 	unsigned int	dp_alloc_top;
diff --git a/arch/sh/include/asm/global_data.h b/arch/sh/include/asm/global_data.h
index 0c09ba9..1b782fc 100644
--- a/arch/sh/include/asm/global_data.h
+++ b/arch/sh/include/asm/global_data.h
@@ -34,6 +34,9 @@ typedef	struct global_data
 	unsigned long	baudrate;
 	unsigned long	cpu_clk;	/* CPU clock in Hz! */
 	unsigned long	have_console;	/* serial_init() was called */
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
+	unsigned long	precon_buf_idx;	/* Pre-Console buffer index */
+#endif
 	phys_size_t	ram_size;	/* RAM size */
 	unsigned long	env_addr;	/* Address  of Environment struct */
 	unsigned long	env_valid;	/* Checksum of Environment valid */
diff --git a/arch/sparc/include/asm/global_data.h b/arch/sparc/include/asm/global_data.h
index 9b14674..a1e4b44 100644
--- a/arch/sparc/include/asm/global_data.h
+++ b/arch/sparc/include/asm/global_data.h
@@ -53,6 +53,9 @@ typedef struct global_data {
 	unsigned long env_valid;	/* Checksum of Environment valid?       */
 	unsigned long have_console;	/* serial_init() was called */

+#ifdef CONFIG_PRE_CONSOLE_BUFFER
+	unsigned long	precon_buf_idx;	/* Pre-Console buffer index */
+#endif
 #if defined(CONFIG_LCD) || defined(CONFIG_VIDEO)
 	unsigned long fb_base;	/* Base address of framebuffer memory   */
 #endif
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index f977dbe..6cf7955 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -40,6 +40,9 @@ typedef	struct global_data {
 	unsigned long	flags;
 	unsigned long	baudrate;
 	unsigned long	have_console;	/* serial_init() was called */
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
+	unsigned long	precon_buf_idx;	/* Pre-Console buffer index */
+#endif
 	unsigned long	reloc_off;	/* Relocation Offset */
 	unsigned long	load_off;	/* Load Offset */
 	unsigned long	env_addr;	/* Address  of Environment struct */
diff --git a/common/console.c b/common/console.c
index b23d933..570196e 100644
--- a/common/console.c
+++ b/common/console.c
@@ -329,6 +329,39 @@ int tstc(void)
 	return serial_tstc();
 }

+#ifdef CONFIG_PRE_CONSOLE_BUFFER
+#define CIRC_BUF_IDX(idx) ((idx) % (unsigned long)CONFIG_PRE_CON_BUF_SZ)
+
+void pre_console_putc(const char c)
+{
+	char *buffer = (char *)CONFIG_PRE_CON_BUF_ADDR;
+
+	buffer[CIRC_BUF_IDX(gd->precon_buf_idx++)] = c;
+}
+
+void pre_console_puts(const char *s)
+{
+	while (*s)
+		pre_console_putc(*s++);
+}
+
+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 @@ void putc(const char c)
 #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 @@ void puts(const char *s)
 #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 @@ int printf(const char *fmt, ...)
 	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 @@ int vprintf(const char *fmt, va_list args)
 	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 @@ int console_init_f(void)
 		gd->flags |= GD_FLG_SILENT;
 #endif

+	print_pre_console_buffer();
+
 	return 0;
 }

--
1.7.5.2.317.g391b14



More information about the U-Boot mailing list