console: Implement pre-console buffer
authorGraeme Russ <graeme.russ@gmail.com>
Thu, 1 Sep 2011 00:48:27 +0000 (00:48 +0000)
committerWolfgang Denk <wd@denx.de>
Wed, 5 Oct 2011 20:03:09 +0000 (22:03 +0200)
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.

13 files changed:
README
arch/arm/include/asm/global_data.h
arch/avr32/include/asm/global_data.h
arch/blackfin/include/asm/global_data.h
arch/m68k/include/asm/global_data.h
arch/microblaze/include/asm/global_data.h
arch/mips/include/asm/global_data.h
arch/nios2/include/asm/global_data.h
arch/powerpc/include/asm/global_data.h
arch/sh/include/asm/global_data.h
arch/sparc/include/asm/global_data.h
arch/x86/include/asm/global_data.h
common/console.c

diff --git a/README b/README
index 91b6695cf90c25269a89bb1fefbea7e392ef0683..dfc7ada61e1e9cc418f3fd8f8648b0382ac000fa 100644 (file)
--- 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 circular 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.
index 4fc51fdc75f2ccaa09a138ae6af7984d18275c85..b85b7fe808f53a0590fb8160e61ff0a91386c6b9 100644 (file)
@@ -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 */
index 4ef8fc570f34524691e59a6f03da60e2dac1fe92..5c654bd5e0325ec845cf7e882422e4dc67a8a765 100644 (file)
@@ -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? */
index eba5e93e212c0199be859697d3dcc5057cf9b752..f7aa71113de0b2765660a766ab33599d33d4649f 100644 (file)
@@ -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? */
index fc486fda58ddf52f00f857380f4f8f498b7574b8..0ba2b43305d0a940538387e9c8208f2b1f61ab79 100644 (file)
@@ -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
index 557ad27e9d4aec121ea646f8e9baf3875752e102..6e8537c8ed13b1ead5a58ba0c2dd37c9be68fb04 100644 (file)
@@ -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 */
index 271a290a51c392926bd41f198997c77c999578d0..b193517889e001fbb91e467ce6aa44b0bdda42dc 100644 (file)
@@ -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 */
index 2c4a719409d41f99206c31aae815239499708503..d9f06645a3ae2aa70d59cda9d894d3319badf0ad 100644 (file)
@@ -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 */
index a33ca2f7b74eac9eb9c38bfba6f1b92aacf91b84..7fcaf384ed766668fe20152a2256b2c25108d36b 100644 (file)
@@ -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;
index 0c09ba9bad7db563d684d4fda45495eb297f49f4..1b782fc77181cd3780f41955440b1ff39a7745a7 100644 (file)
@@ -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 */
index 9b146748d96aaee8e871fc3d10320a254bbaf963..a1e4b44aac8973d94e256f1b9aea1c01cc231b8d 100644 (file)
@@ -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
index f8a16d646fd41db195838a0c667d3de0c0679a96..f177a4fa3b6859ee44c1871c3dae2feb3ca67c55 100644 (file)
@@ -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 */
index b23d933d2c35742521c34aad25852b2f553ac4c6..f17875ead007703a76aec99a09c0f3705e759773 100644 (file)
@@ -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)
+
+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 @@ 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;
 }