[U-Boot] [PATCH 0/2] console: Squelch and pre-console buffer

This is a more complete followup patch to my original 'Pre-console buffer' patch. This series includes squelching of all console I/O if gd->have_console is 0 (console not initialised yet) unless the board is configured to use the pre-console buffer (in which case console output prior to the console being initialised is redirected to the buffer - All console input is still squelched prior to the console being initialised)
If the pre-console buffer is enabled, the buffer is sent to console as soon as the console is initialised.
Graeme Russ (2): console: Squelch pre-console output in console functions console: Implement pre-console buffer
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/cpu/mpc5xxx/i2c.c | 30 +++++---------- arch/powerpc/cpu/mpc8xx/i2c.c | 18 +++------ arch/powerpc/include/asm/global_data.h | 3 + arch/sh/include/asm/global_data.h | 3 + arch/sparc/include/asm/global_data.h | 4 +- arch/x86/include/asm/global_data.h | 3 + common/console.c | 60 +++++++++++++++++++++++++++++ drivers/i2c/ppc4xx_i2c.c | 5 +-- drivers/i2c/soft_i2c.c | 1 - 16 files changed, 110 insertions(+), 38 deletions(-)
-- 1.7.5.2.317.g391b14

There are some locations in the code which anticipate printf() being called before the console is ready by squelching printf() on gd->have_console. Move this squelching into printf(), vprintf(), puts() and putc(). Also make tstc() and getc() return 0 if console is not yet initialised
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/powerpc/cpu/mpc5xxx/i2c.c | 30 ++++++++++-------------------- arch/powerpc/cpu/mpc8xx/i2c.c | 18 ++++++------------ common/console.c | 18 ++++++++++++++++++ drivers/i2c/ppc4xx_i2c.c | 5 +---- drivers/i2c/soft_i2c.c | 1 - 5 files changed, 35 insertions(+), 37 deletions(-)
diff --git a/arch/powerpc/cpu/mpc5xxx/i2c.c b/arch/powerpc/cpu/mpc5xxx/i2c.c index 9fb330f..f9d293b 100644 --- a/arch/powerpc/cpu/mpc5xxx/i2c.c +++ b/arch/powerpc/cpu/mpc5xxx/i2c.c @@ -332,8 +332,7 @@ static int mpc_get_fdr(int speed) if (gd->flags & GD_FLG_RELOC) { fdr = divider; } else { - if (gd->have_console) - printf("%ld kHz, ", best_speed / 1000); + printf("%ld kHz, ", best_speed / 1000); return divider; } } @@ -374,34 +373,29 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len) xaddr[3] = addr & 0xFF;
if (wait_for_bb()) { - if (gd->have_console) - printf("i2c_read: bus is busy\n"); + printf("i2c_read: bus is busy\n"); goto Done; }
mpc_reg_out(®s->mcr, I2C_STA, I2C_STA); if (do_address(chip, 0)) { - if (gd->have_console) - printf("i2c_read: failed to address chip\n"); + printf("i2c_read: failed to address chip\n"); goto Done; }
if (send_bytes(chip, &xaddr[4-alen], alen)) { - if (gd->have_console) - printf("i2c_read: send_bytes failed\n"); + printf("i2c_read: send_bytes failed\n"); goto Done; }
mpc_reg_out(®s->mcr, I2C_RSTA, I2C_RSTA); if (do_address(chip, 1)) { - if (gd->have_console) - printf("i2c_read: failed to address chip\n"); + printf("i2c_read: failed to address chip\n"); goto Done; }
if (receive_bytes(chip, (char *)buf, len)) { - if (gd->have_console) - printf("i2c_read: receive_bytes failed\n"); + printf("i2c_read: receive_bytes failed\n"); goto Done; }
@@ -423,27 +417,23 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len) xaddr[3] = addr & 0xFF;
if (wait_for_bb()) { - if (gd->have_console) - printf("i2c_write: bus is busy\n"); + printf("i2c_write: bus is busy\n"); goto Done; }
mpc_reg_out(®s->mcr, I2C_STA, I2C_STA); if (do_address(chip, 0)) { - if (gd->have_console) - printf("i2c_write: failed to address chip\n"); + printf("i2c_write: failed to address chip\n"); goto Done; }
if (send_bytes(chip, &xaddr[4-alen], alen)) { - if (gd->have_console) - printf("i2c_write: send_bytes failed\n"); + printf("i2c_write: send_bytes failed\n"); goto Done; }
if (send_bytes(chip, (char *)buf, len)) { - if (gd->have_console) - printf("i2c_write: send_bytes failed\n"); + printf("i2c_write: send_bytes failed\n"); goto Done; }
diff --git a/arch/powerpc/cpu/mpc8xx/i2c.c b/arch/powerpc/cpu/mpc8xx/i2c.c index 338caba..1ca51fd 100644 --- a/arch/powerpc/cpu/mpc8xx/i2c.c +++ b/arch/powerpc/cpu/mpc8xx/i2c.c @@ -633,22 +633,19 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen, &xaddr[4-alen]); if (rc != 0) { - if (gd->have_console) - printf("i2c_read: i2c_send failed (%d)\n", rc); + printf("i2c_read: i2c_send failed (%d)\n", rc); return 1; }
rc = i2c_receive(&state, chip, 0, I2CF_STOP_COND, len, buffer); if (rc != 0) { - if (gd->have_console) - printf("i2c_read: i2c_receive failed (%d)\n", rc); + printf("i2c_read: i2c_receive failed (%d)\n", rc); return 1; }
rc = i2c_doio(&state); if (rc != 0) { - if (gd->have_console) - printf("i2c_read: i2c_doio failed (%d)\n", rc); + printf("i2c_read: i2c_doio failed (%d)\n", rc); return 1; } return 0; @@ -683,22 +680,19 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen, &xaddr[4-alen]); if (rc != 0) { - if (gd->have_console) - printf("i2c_write: first i2c_send failed (%d)\n", rc); + printf("i2c_write: first i2c_send failed (%d)\n", rc); return 1; }
rc = i2c_send(&state, 0, 0, I2CF_STOP_COND, len, buffer); if (rc != 0) { - if (gd->have_console) - printf("i2c_write: second i2c_send failed (%d)\n", rc); + printf("i2c_write: second i2c_send failed (%d)\n", rc); return 1; }
rc = i2c_doio(&state); if (rc != 0) { - if (gd->have_console) - printf("i2c_write: i2c_doio failed (%d)\n", rc); + printf("i2c_write: i2c_doio failed (%d)\n", rc); return 1; } return 0; diff --git a/common/console.c b/common/console.c index 8c650e0..b23d933 100644 --- a/common/console.c +++ b/common/console.c @@ -298,6 +298,9 @@ int getc(void) return 0; #endif
+ if (!gd->have_console) + return 0; + if (gd->flags & GD_FLG_DEVINIT) { /* Get from the standard input */ return fgetc(stdin); @@ -314,6 +317,9 @@ int tstc(void) return 0; #endif
+ if (!gd->have_console) + return 0; + if (gd->flags & GD_FLG_DEVINIT) { /* Test the standard input */ return ftstc(stdin); @@ -335,6 +341,9 @@ void putc(const char c) return; #endif
+ if (!gd->have_console) + return; + if (gd->flags & GD_FLG_DEVINIT) { /* Send to the standard output */ fputc(stdout, c); @@ -356,6 +365,9 @@ void puts(const char *s) return; #endif
+ if (!gd->have_console) + return; + if (gd->flags & GD_FLG_DEVINIT) { /* Send to the standard output */ fputs(stdout, s); @@ -371,6 +383,9 @@ int printf(const char *fmt, ...) uint i; char printbuffer[CONFIG_SYS_PBSIZE];
+ if (!gd->have_console) + return 0; + va_start(args, fmt);
/* For this to work, printbuffer must be larger than @@ -389,6 +404,9 @@ int vprintf(const char *fmt, va_list args) uint i; char printbuffer[CONFIG_SYS_PBSIZE];
+ if (!gd->have_console) + return 0; + /* For this to work, printbuffer must be larger than * anything we ever want to print. */ diff --git a/drivers/i2c/ppc4xx_i2c.c b/drivers/i2c/ppc4xx_i2c.c index c1cbe55..53fedd5 100644 --- a/drivers/i2c/ppc4xx_i2c.c +++ b/drivers/i2c/ppc4xx_i2c.c @@ -396,10 +396,7 @@ static int ppc4xx_i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer, #endif if ((ret = i2c_transfer(read, chip << 1, &xaddr[4 - alen], alen, buffer, len)) != 0) { - if (gd->have_console) { - printf("I2C %s: failed %d\n", - read ? "read" : "write", ret); - } + printf("I2C %s: failed %d\n", read ? "read" : "write", ret);
return 1; } diff --git a/drivers/i2c/soft_i2c.c b/drivers/i2c/soft_i2c.c index 9b02e89..36c6114 100644 --- a/drivers/i2c/soft_i2c.c +++ b/drivers/i2c/soft_i2c.c @@ -119,7 +119,6 @@ DECLARE_GLOBAL_DATA_PTR;
#ifdef DEBUG_I2C #define PRINTD(fmt,args...) do { \ - if (gd->have_console) \ printf (fmt ,##args); \ } while (0) #else

On Monday, August 29, 2011 08:14:05 Graeme Russ wrote:
--- a/drivers/i2c/soft_i2c.c +++ b/drivers/i2c/soft_i2c.c
#ifdef DEBUG_I2C #define PRINTD(fmt,args...) do { \
- if (gd->have_console) \ printf (fmt ,##args); \ } while (0)
#else
the "do {} while (0)" can go away now -mike

Dear Mike Frysinger,
In message 201108301316.56595.vapier@gentoo.org you wrote:
On Monday, August 29, 2011 08:14:05 Graeme Russ wrote:
--- a/drivers/i2c/soft_i2c.c +++ b/drivers/i2c/soft_i2c.c =20 #ifdef DEBUG_I2C #define PRINTD(fmt,args...) do { \
- if (gd->have_console) \ printf (fmt ,##args); \ } while (0)
#else
the "do {} while (0)" can go away now
It is safer to keep it, especially with the if construct.
Best regards,
Wolfgang Denk

Hi Graeme,
On Mon, Aug 29, 2011 at 5:14 AM, Graeme Russ graeme.russ@gmail.com wrote:
There are some locations in the code which anticipate printf() being called before the console is ready by squelching printf() on gd->have_console. Move this squelching into printf(), vprintf(), puts() and putc(). Also make tstc() and getc() return 0 if console is not yet initialised
Signed-off-by: Graeme Russ graeme.russ@gmail.com
This stops U-Boot from hanging if I add a printf() prior to console init in board_init_f. Great!
Tested-by: Simon Glass sjg@chromium.org
Regards, Simon
arch/powerpc/cpu/mpc5xxx/i2c.c | 30 ++++++++++-------------------- arch/powerpc/cpu/mpc8xx/i2c.c | 18 ++++++------------ common/console.c | 18 ++++++++++++++++++ drivers/i2c/ppc4xx_i2c.c | 5 +---- drivers/i2c/soft_i2c.c | 1 - 5 files changed, 35 insertions(+), 37 deletions(-)
diff --git a/arch/powerpc/cpu/mpc5xxx/i2c.c b/arch/powerpc/cpu/mpc5xxx/i2c.c index 9fb330f..f9d293b 100644 --- a/arch/powerpc/cpu/mpc5xxx/i2c.c +++ b/arch/powerpc/cpu/mpc5xxx/i2c.c
[snip]

Dear Graeme Russ,
In message 1314620046-26187-2-git-send-email-graeme.russ@gmail.com you wrote:
There are some locations in the code which anticipate printf() being called before the console is ready by squelching printf() on gd->have_console. Move this squelching into printf(), vprintf(), puts() and putc(). Also make tstc() and getc() return 0 if console is not yet initialised
Signed-off-by: Graeme Russ graeme.russ@gmail.com
arch/powerpc/cpu/mpc5xxx/i2c.c | 30 ++++++++++-------------------- arch/powerpc/cpu/mpc8xx/i2c.c | 18 ++++++------------ common/console.c | 18 ++++++++++++++++++ drivers/i2c/ppc4xx_i2c.c | 5 +---- drivers/i2c/soft_i2c.c | 1 - 5 files changed, 35 insertions(+), 37 deletions(-)
Applied, thanks.
Best regards,
Wolfgang Denk

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 first (CONFIG_PRE_CON_BUF_SZ -1) bytes (need to allow for a null terminator). Any remaining characters are silently dropped.
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- 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 | 4 ++- arch/x86/include/asm/global_data.h | 3 ++ common/console.c | 50 ++++++++++++++++++++++++++-- 12 files changed, 79 insertions(+), 5 deletions(-)
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..445aa8b 100644 --- a/arch/sparc/include/asm/global_data.h +++ b/arch/sparc/include/asm/global_data.h @@ -52,7 +52,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 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..b3d2a53 100644 --- a/common/console.c +++ b/common/console.c @@ -329,6 +329,30 @@ int tstc(void) return serial_tstc(); }
+#ifdef CONFIG_PRE_CONSOLE_BUFFER +void pre_console_putc(const char c) +{ + char *buffer = (char *)CONFIG_SYS_TMP_CON_BUF_ADDR; + + if (gd->precon_buf_idx < CONFIG_SYS_TMP_CON_BUF_SZ) + buffer[gd->precon_buf_idx++] = c; +} + +void pre_console_puts(const char *s) +{ + while (*s) + pre_console_putc(*s++); +} + +void print_pre_console_buffer(void) +{ + char *buffer = (char *)CONFIG_SYS_TMP_CON_BUF_ADDR; + + buffer[gd->precon_buf_idx] = 0x00; + puts(buffer); +} +#endif + void putc(const char c) { #ifdef CONFIG_SILENT_CONSOLE @@ -341,8 +365,12 @@ void putc(const char c) return; #endif
- if (!gd->have_console) + if (!gd->have_console) { +#ifdef CONFIG_PRE_CONSOLE_BUFFER + pre_console_putc(c); +#endif return; + }
if (gd->flags & GD_FLG_DEVINIT) { /* Send to the standard output */ @@ -365,8 +393,12 @@ void puts(const char *s) return; #endif
- if (!gd->have_console) + if (!gd->have_console) { +#ifdef CONFIG_PRE_CONSOLE_BUFFER + pre_console_puts(s); +#endif return; + }
if (gd->flags & GD_FLG_DEVINIT) { /* Send to the standard output */ @@ -383,8 +415,11 @@ int printf(const char *fmt, ...) uint i; char printbuffer[CONFIG_SYS_PBSIZE];
- if (!gd->have_console) +#ifndef CONFIG_PRE_CONSOLE_BUFFER + if (!gd->have_console) { return 0; + } +#endif
va_start(args, fmt);
@@ -404,8 +439,11 @@ int vprintf(const char *fmt, va_list args) uint i; char printbuffer[CONFIG_SYS_PBSIZE];
- if (!gd->have_console) +#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 +585,10 @@ int console_init_f(void) gd->flags |= GD_FLG_SILENT; #endif
+#ifdef CONFIG_PRE_CONSOLE_BUFFER + print_pre_console_buffer(); +#endif + return 0; }

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@gmail.com --- Changes Since V1 - Implemented circular buffer - Trivial code style corrections
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 | 49 +++++++++++++++++++++++++++- 12 files changed, 80 insertions(+), 2 deletions(-)
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..ae87148 100644 --- a/common/console.c +++ b/common/console.c @@ -329,6 +329,35 @@ int tstc(void) return serial_tstc(); }
+#ifdef CONFIG_PRE_CONSOLE_BUFFER +#define CIRC_BUF_IDX(idx) ((idx) % 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++)]); +} +#endif + void putc(const char c) { #ifdef CONFIG_SILENT_CONSOLE @@ -341,8 +370,12 @@ void putc(const char c) return; #endif
- if (!gd->have_console) + if (!gd->have_console) { +#ifdef CONFIG_PRE_CONSOLE_BUFFER + pre_console_putc(c); +#endif return; + }
if (gd->flags & GD_FLG_DEVINIT) { /* Send to the standard output */ @@ -365,8 +398,12 @@ void puts(const char *s) return; #endif
- if (!gd->have_console) + if (!gd->have_console) { +#ifdef CONFIG_PRE_CONSOLE_BUFFER + pre_console_puts(s); +#endif return; + }
if (gd->flags & GD_FLG_DEVINIT) { /* Send to the standard output */ @@ -383,8 +420,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 +443,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 +588,10 @@ int console_init_f(void) gd->flags |= GD_FLG_SILENT; #endif
+#ifdef CONFIG_PRE_CONSOLE_BUFFER + print_pre_console_buffer(); +#endif + return 0; }
-- 1.7.5.2.317.g391b14

On Tuesday, August 30, 2011 08:49:41 Graeme Russ wrote:
- if (!gd->have_console)
- if (!gd->have_console) {
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
pre_console_putc(c);
+#endif return;
- }
add inline stubs for the pre_console_xxx helpers and you can drop all the ifdef's through out the rest of the code
#ifdef CONFIG_PRE_CONSOLE_BUFFER ... normal defines for these ... #else static inline void pre_console_putc(const char c) {} static inline void pre_console_puts(const char *s) {} #endif -mike

Hi Graeme,
On Tue, Aug 30, 2011 at 5:49 AM, Graeme Russ graeme.russ@gmail.com wrote:
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)
Please can you add these to the README?
Also I wonder if it is safe to have boards setting the buffer address. Should not arch/xxx/lib/board.c work this out based on CONFIG_SYS_INIT_SP_ADDR as it does all the other memory areas?
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@gmail.com
Changes Since V1 - Implemented circular buffer - Trivial code style corrections
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 | 49 +++++++++++++++++++++++++++- 12 files changed, 80 insertions(+), 2 deletions(-)
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..ae87148 100644 --- a/common/console.c +++ b/common/console.c @@ -329,6 +329,35 @@ int tstc(void) return serial_tstc(); }
+#ifdef CONFIG_PRE_CONSOLE_BUFFER +#define CIRC_BUF_IDX(idx) ((idx) % CONFIG_PRE_CON_BUF_SZ)
The division here sticks in the craw, but unless we go with CONFIG_PRE_CON_BUF_SZ_LOG2 then I don't see an easy way around it, and since this is serial output we can't honestly claim to worry much about performance.
+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;
Gosh this is clever - perhaps a little comment?
- while (i < gd->precon_buf_idx)
- putc(buffer[CIRC_BUF_IDX(i++)]);
+} +#endif
void putc(const char c) { #ifdef CONFIG_SILENT_CONSOLE @@ -341,8 +370,12 @@ void putc(const char c) return; #endif
- if (!gd->have_console)
- if (!gd->have_console) {
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
- pre_console_putc(c);
+#endif return;
- }
if (gd->flags & GD_FLG_DEVINIT) { /* Send to the standard output */ @@ -365,8 +398,12 @@ void puts(const char *s) return; #endif
- if (!gd->have_console)
- if (!gd->have_console) {
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
- pre_console_puts(s);
+#endif return;
- }
if (gd->flags & GD_FLG_DEVINIT) { /* Send to the standard output */ @@ -383,8 +420,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 +443,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 +588,10 @@ int console_init_f(void) gd->flags |= GD_FLG_SILENT; #endif
+#ifdef CONFIG_PRE_CONSOLE_BUFFER
- print_pre_console_buffer();
+#endif
return 0; }
-- 1.7.5.2.317.g391b14
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Dear Simon Glass,
In message CAPnjgZ1fXCCFDcwCWgZD7H-siVEV-H+Ks5TPeiT=nGS743fzcg@mail.gmail.com you wrote:
...
+#define CIRC_BUF_IDX(idx) ((idx) % CONFIG_PRE_CON_BUF_SZ)
The division here sticks in the craw, but unless we go with
Does it? Why?
CONFIG_PRE_CON_BUF_SZ_LOG2 then I don't see an easy way around it, and since this is serial output we can't honestly claim to worry much about performance.
Please see my previous posting (http://article.gmane.org/gmane.comp.boot-loaders.u-boot/106810)
I don't think 3 additional addembler instructions really play a big role here.
Best regards,
Wolfgang Denk

On Tuesday, August 30, 2011 15:52:38 Wolfgang Denk wrote:
Simon Glass wrote:
+#define CIRC_BUF_IDX(idx) ((idx) % CONFIG_PRE_CON_BUF_SZ)
The division here sticks in the craw, but unless we go with
Does it? Why?
CONFIG_PRE_CON_BUF_SZ_LOG2 then I don't see an easy way around it, and since this is serial output we can't honestly claim to worry much about performance.
Please see my previous posting (http://article.gmane.org/gmane.comp.boot-loaders.u-boot/106810)
I don't think 3 additional addembler instructions really play a big role here.
i'm pretty sure if you define CONFIG_PRE_CON_BUF_SZ as a power of 2 value, you get nice & simple assembly code. so if the generated code is undesirable, pick a CONFIG value that is power-of-2 ? -mike

Dear Mike Frysinger,
In message 201108301558.08010.vapier@gentoo.org you wrote:
Please see my previous posting (http://article.gmane.org/gmane.comp.boot-loaders.u-boot/106810)
I don't think 3 additional addembler instructions really play a big role here.
i'm pretty sure if you define CONFIG_PRE_CON_BUF_SZ as a power of 2 value, you get nice & simple assembly code. so if the generated code is undesirable, pick a CONFIG value that is power-of-2 ?
This was the test code I compiled:
--------------------------------------------- #define CONFIG_SYS_TMP_CON_BUF_SZ 1024
int foo(int i) { return i & (CONFIG_SYS_TMP_CON_BUF_SZ-1); }
int bar(int i) { return i % CONFIG_SYS_TMP_CON_BUF_SZ; } ---------------------------------------------
So was actually checking for a power-of-2 value.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Tue, Aug 30, 2011 at 1:08 PM, Wolfgang Denk wd@denx.de wrote:
Dear Mike Frysinger,
In message 201108301558.08010.vapier@gentoo.org you wrote:
Please see my previous posting (http://article.gmane.org/gmane.comp.boot-loaders.u-boot/106810)
I don't think 3 additional addembler instructions really play a big role here.
i'm pretty sure if you define CONFIG_PRE_CON_BUF_SZ as a power of 2 value, you get nice & simple assembly code. so if the generated code is undesirable, pick a CONFIG value that is power-of-2 ?
This was the test code I compiled:
#define CONFIG_SYS_TMP_CON_BUF_SZ 1024
int foo(int i) { return i & (CONFIG_SYS_TMP_CON_BUF_SZ-1); }
int bar(int i) { return i % CONFIG_SYS_TMP_CON_BUF_SZ; }
So was actually checking for a power-of-2 value.
In case it is interesting (which may be unlikely) here is the code generated by my compiler (common code stripped) for your example, and one I added. It seems that % makes it worry about sign.
#define CONFIG_SYS_TMP_CON_BUF_SZ 1024
int foo(int i) { return i & (CONFIG_SYS_TMP_CON_BUF_SZ-1); 14: e1a03b03 lsl r3, r3, #22 18: e1a03b23 lsr r3, r3, #22 }
int bar(int i) { return i % CONFIG_SYS_TMP_CON_BUF_SZ; 40: e1a02fc3 asr r2, r3, #31 44: e1a02b22 lsr r2, r2, #22 48: e0833002 add r3, r3, r2 4c: e1a03b03 lsl r3, r3, #22 50: e1a03b23 lsr r3, r3, #22 54: e0623003 rsb r3, r2, r3 }
int lee(int i) { return i % (CONFIG_SYS_TMP_CON_BUF_SZ - 1); 7c: e3003803 movw r3, #2051 ; 0x803 80: e3483020 movt r3, #32800 ; 0x8020 84: e0c31293 smull r1, r3, r3, r2 88: e0833002 add r3, r3, r2 8c: e1a014c3 asr r1, r3, #9 90: e1a03fc2 asr r3, r2, #31 94: e0633001 rsb r3, r3, r1 98: e1a01003 mov r1, r3 9c: e1a01501 lsl r1, r1, #10 a0: e0631001 rsb r1, r3, r1 a4: e0613002 rsb r3, r1, r2 }
Regards, Simon
Best regards,
Wolfgang Denk
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de "Maintain an awareness for contribution -- to your schedule, your project, our company." - A Group of Employees

Dear Simon Glass,
In message CAPnjgZ1dQXMVeFk47=Gg5y+TCHG7WTdGk0b1WjSqOBhu2d0xnQ@mail.gmail.com you wrote:
In case it is interesting (which may be unlikely) here is the code generated by my compiler (common code stripped) for your example, and
Which architecture / which compiler is this?
one I added. It seems that % makes it worry about sign.
Indeed! We should use unsigned numbers here. MUCH better now:
unsigned int ufoo(unsigned int i) { return i & (CONFIG_SYS_TMP_CON_BUF_SZ-1); }
For ARM, BUF_SZ = 1024
mov r0, r0, asl #22 mov r0, r0, lsr #22
For PPC, BUF_SZ = 1024
rlwinm 3,3,0,22,31
The following two entries make no sense, just for completeness:
For ARM, BUF_SZ = 1021 (Note: 1021 is a prime number)
and r0, r0, #1020
For PPC, BUF_SZ = 1021
rlwinm 3,3,0,22,29
unsigned int ubar(unsigned int i) { return i % CONFIG_SYS_TMP_CON_BUF_SZ; }
For ARM, BUF_SZ = 1024
mov r0, r0, asl #22 mov r0, r0, lsr #22
For PPC, BUF_SZ = 1024
rlwinm 3,3,0,22,31
For ARM, BUF_SZ = 1021
ldr r2, .L11 mov ip, r0 umull r1, r3, r2, r0 rsb r1, r3, r0 add r3, r3, r1, lsr #1 mov r3, r3, lsr #9 mov r0, r3, asl #10 sub r0, r0, r3, asl #2 add r0, r0, r3 rsb r0, r0, ip
For PPC, BUF_SZ = 1021
lis 0,0xc0 ori 0,0,36973 mulhwu 0,3,0 subf 9,0,3 srwi 9,9,1 add 0,0,9 srwi 0,0,9 mulli 0,0,1021 subf 3,0,3
So indeed we should use unsigned arithmetics, and try to use power-of-two sizes where possible.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Tue, Aug 30, 2011 at 1:57 PM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message CAPnjgZ1dQXMVeFk47=Gg5y+TCHG7WTdGk0b1WjSqOBhu2d0xnQ@mail.gmail.com you wrote:
In case it is interesting (which may be unlikely) here is the code generated by my compiler (common code stripped) for your example, and
Which architecture / which compiler is this?
It was ARM, gcc version 4.4.3.
one I added. It seems that % makes it worry about sign.
Indeed! We should use unsigned numbers here. MUCH better now:
Yes it is much better. Perhaps an (unsigned) cast in the C code is better than hoping that the board author uses 1024U or similar.
unsigned int ufoo(unsigned int i) { return i & (CONFIG_SYS_TMP_CON_BUF_SZ-1); }
For ARM, BUF_SZ = 1024
mov r0, r0, asl #22 mov r0, r0, lsr #22
For PPC, BUF_SZ = 1024
rlwinm 3,3,0,22,31
The following two entries make no sense, just for completeness:
For ARM, BUF_SZ = 1021 (Note: 1021 is a prime number)
and r0, r0, #1020
For PPC, BUF_SZ = 1021
rlwinm 3,3,0,22,29
unsigned int ubar(unsigned int i) { return i % CONFIG_SYS_TMP_CON_BUF_SZ; }
For ARM, BUF_SZ = 1024
mov r0, r0, asl #22 mov r0, r0, lsr #22
For PPC, BUF_SZ = 1024
rlwinm 3,3,0,22,31
For ARM, BUF_SZ = 1021
ldr r2, .L11 mov ip, r0 umull r1, r3, r2, r0 rsb r1, r3, r0 add r3, r3, r1, lsr #1 mov r3, r3, lsr #9 mov r0, r3, asl #10 sub r0, r0, r3, asl #2 add r0, r0, r3 rsb r0, r0, ip
For PPC, BUF_SZ = 1021
lis 0,0xc0 ori 0,0,36973 mulhwu 0,3,0 subf 9,0,3 srwi 9,9,1 add 0,0,9 srwi 0,0,9 mulli 0,0,1021 subf 3,0,3
So indeed we should use unsigned arithmetics, and try to use power-of-two sizes where possible.
Yes indeed.
Regards, Simon
Best regards,
Wolfgang Denk
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de You can't evaluate a man by logic alone. -- McCoy, "I, Mudd", stardate 4513.3

Hi Simon, Mike, Wolfgang,
On Wed, Aug 31, 2011 at 7:02 AM, Simon Glass sjg@chromium.org wrote:
Hi Wolfgang,
On Tue, Aug 30, 2011 at 1:57 PM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message CAPnjgZ1dQXMVeFk47=Gg5y+TCHG7WTdGk0b1WjSqOBhu2d0xnQ@mail.gmail.com you wrote:
In case it is interesting (which may be unlikely) here is the code generated by my compiler (common code stripped) for your example, and
Which architecture / which compiler is this?
It was ARM, gcc version 4.4.3.
one I added. It seems that % makes it worry about sign.
Indeed! We should use unsigned numbers here. MUCH better now:
Yes it is much better. Perhaps an (unsigned) cast in the C code is better than hoping that the board author uses 1024U or similar.
[snip]
So indeed we should use unsigned arithmetics, and try to use power-of-two sizes where possible.
I'll do another spin (probably not tonight - maybe tomorrow) which covers:
- inline stub functions to reduce #ifdef clutter - unsigned casting of buffer size - Documentation in README including the fact that setting the buffer size to a value which is a power of 2 will provide more optimised code (for reasonably sane compilers ;))
Now as for the calculation of the buffer address... It could be calculated dynamically in board.c but this will require another ulong in gd and the pre-console buffer will be unusable until the calculation is done (and any inadvertant printf() before this will likely cause some very bad behaviour) Also, x86 does not do these calculations dynamically and I also think it might make the pre-buffer console avaialble in early init_f
Getting back to gd for a sec - This patch (like the flagify patch set I posted before) impacts the structure of gd. Does this trigger in increment to the API Version? And as observed before, if the structure of gd is fixed for any given API version, then we have a problem with all the #ifdef's that are already in gd. If it _is_ the case that the API version expects a particular fixed structure for gd, then maybe we need to remove all the #ifdefs from gd - Yes it will lead to a few dead ulongs for a few boards, but I don't see any practical alternatives. I did think about looking at doing some kind of CRC on the gd struct (like the generated asm-offsets), but I could not think of a way to do it)
Regards,
Graeme

Hi Wolfgang
On Wed, Aug 31, 2011 at 9:00 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon, Mike, Wolfgang,
On Wed, Aug 31, 2011 at 7:02 AM, Simon Glass sjg@chromium.org wrote:
Hi Wolfgang,
On Tue, Aug 30, 2011 at 1:57 PM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message CAPnjgZ1dQXMVeFk47=Gg5y+TCHG7WTdGk0b1WjSqOBhu2d0xnQ@mail.gmail.com you wrote:
[snip]
Getting back to gd for a sec - This patch (like the flagify patch set I posted before) impacts the structure of gd. Does this trigger in increment to the API Version? And as observed before, if the structure of gd is fixed for any given API version, then we have a problem with all the #ifdef's that are already in gd. If it _is_ the case that the API version expects a particular fixed structure for gd, then maybe we need to remove all the #ifdefs from gd - Yes it will lead to a few dead ulongs for a few boards, but I don't see any practical alternatives. I did think about looking at doing some kind of CRC on the gd struct (like the generated asm-offsets), but I could not think of a way to do it)
Another gd related thought - Is it safe to assume that gd will be cleared? I hope so, as the pre-buffer console assumes gd->precon_buf_idx is initially zero.
Regards,
Graeme

On Tuesday, August 30, 2011 19:39:20 Graeme Russ wrote:
Another gd related thought - Is it safe to assume that gd will be cleared? I hope so, as the pre-buffer console assumes gd->precon_buf_idx is initially zero.
i'm pretty sure you can. the Blackfin arch certainly memset's it to 0. -mike

Hi Wolfgang,
On Tue, Aug 30, 2011 at 12:52 PM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message CAPnjgZ1fXCCFDcwCWgZD7H-siVEV-H+Ks5TPeiT=nGS743fzcg@mail.gmail.com you wrote:
...
+#define CIRC_BUF_IDX(idx) ((idx) % CONFIG_PRE_CON_BUF_SZ)
The division here sticks in the craw, but unless we go with
Does it? Why?
Only because of the division. But as Mike mentions later, the compiler will avoid it for powers of two. So all is well.
CONFIG_PRE_CON_BUF_SZ_LOG2 then I don't see an easy way around it, and since this is serial output we can't honestly claim to worry much about performance.
Please see my previous posting (http://article.gmane.org/gmane.comp.boot-loaders.u-boot/106810)
I don't think 3 additional addembler instructions really play a big role here.
Yes I saw it, thanks.
Regards, Simon
Best regards,
Wolfgang Denk
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de Every time history repeats itself the price goes up.

Date: Mon, 29 Aug 2011 21:04:45 +1000 Subject: [PATCH V3] console: Implement pre-console buffer
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@gmail.com --- 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

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@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

On Wednesday, August 31, 2011 08:58:25 Graeme Russ wrote:
Allow redirection of console output prior to console initialisation to a temporary buffer.
looks good to me. doesnt apply, but that's because this needs your other gd rework patch.
Acked-by: Mike Frysinger vapier@gentoo.org -mike

Hi Mike,
On 01/09/11 01:09, Mike Frysinger wrote:
On Wednesday, August 31, 2011 08:58:25 Graeme Russ wrote:
Allow redirection of console output prior to console initialisation to a temporary buffer.
looks good to me. doesnt apply, but that's because this needs your other gd rework patch.
Acked-by: Mike Frysinger vapier@gentoo.org -mike
It should apply - This patch does not depend on my 'flagify' patch set
Regards,
Graeme

On Wednesday, August 31, 2011 17:15:25 Graeme Russ wrote:
On 01/09/11 01:09, Mike Frysinger wrote:
On Wednesday, August 31, 2011 08:58:25 Graeme Russ wrote:
Allow redirection of console output prior to console initialisation to a temporary buffer.
looks good to me. doesnt apply, but that's because this needs your other gd rework patch.
Acked-by: Mike Frysinger vapier@gentoo.org -mike
It should apply - This patch does not depend on my 'flagify' patch set
err, yeah, i skipped 1/2 since the subject lost "2/2" but gained "v4" :)
no biggie -mike

Hi Mike
On Thursday, September 1, 2011, Mike Frysinger vapier@gentoo.org wrote:
On Wednesday, August 31, 2011 17:15:25 Graeme Russ wrote:
On 01/09/11 01:09, Mike Frysinger wrote:
On Wednesday, August 31, 2011 08:58:25 Graeme Russ wrote:
Allow redirection of console output prior to console initialisation to
a
temporary buffer.
looks good to me. doesnt apply, but that's because this needs your
other
gd rework patch.
Acked-by: Mike Frysinger vapier@gentoo.org -mike
It should apply - This patch does not depend on my 'flagify' patch set
err, yeah, i skipped 1/2 since the subject lost "2/2" but gained "v4" :)
no biggie
So it applies?
Regards
Graeme

Hi Mike,
On Thu, Sep 1, 2011 at 8:44 AM, Mike Frysinger vapier@gentoo.org wrote:
On Wednesday, August 31, 2011 17:59:19 Graeme Russ wrote:
So it applies?
yep. and even compiles without warnings.
Ah, but does it work ;)
Regards,
Graeme

Hi Graeme,
On Wed, Aug 31, 2011 at 5:58 AM, Graeme Russ graeme.russ@gmail.com wrote:
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@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
nit: circular. Just a suggestion if you like: you could also offer guidance for the location of the buffer, something like:
You can place the buffer at the top of memory by adding something like this in your board config file:
#define CONFIG_PRE_CON_BUF_ADDR (CONFIG_SYS_INIT_RAM_ADDR + \ CONFIG_SYS_INIT_RAM_SIZE - \ CONFIG_PRE_CON_BUF_SZ) #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_PRE_CON_BUF_ADDR - \ GENERATED_GBL_DATA_SIZE)
- bytes are output before the console is initialised, the
- earlier bytes are discarded.
Anyway:
Acked-by: Simon Glass sjg@chromium.org
Regards, Simon

Dear Simon Glass,
In message CAPnjgZ1bMkN3xoNCqtg1CLMa=0rgpHsuyHyZg5yOkR3Hk+v+Bw@mail.gmail.com you wrote:
nit: circular. Just a suggestion if you like: you could also offer guidance for the location of the buffer, something like:
You can place the buffer at the top of memory by adding something like this in your board config file:
#define CONFIG_PRE_CON_BUF_ADDR (CONFIG_SYS_INIT_RAM_ADDR + \ CONFIG_SYS_INIT_RAM_SIZE - \ CONFIG_PRE_CON_BUF_SZ) #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_PRE_CON_BUF_ADDR - \ GENERATED_GBL_DATA_SIZE)
That would only make sense if these were generic options that are used across all boards and architectures.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Wed, Aug 31, 2011 at 12:18 PM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message CAPnjgZ1bMkN3xoNCqtg1CLMa=0rgpHsuyHyZg5yOkR3Hk+v+Bw@mail.gmail.com you wrote:
nit: circular. Just a suggestion if you like: you could also offer guidance for the location of the buffer, something like:
You can place the buffer at the top of memory by adding something like this in your board config file:
#define CONFIG_PRE_CON_BUF_ADDR (CONFIG_SYS_INIT_RAM_ADDR + \ CONFIG_SYS_INIT_RAM_SIZE - \ CONFIG_PRE_CON_BUF_SZ) #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_PRE_CON_BUF_ADDR - \ GENERATED_GBL_DATA_SIZE)
That would only make sense if these were generic options that are used across all boards and architectures.
Yes ok - its' already decided not to put this code in arch/xxx/board.c so let's leave this out then.
Regards, Simon
Best regards,
Wolfgang Denk
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de If it went on at this rate, in several billion years he'd be rich beyond his wildest dreams! - Terry Pratchett, _Soul Music_

On Wednesday, August 31, 2011 16:05:38 Simon Glass wrote:
On Wed, Aug 31, 2011 at 12:18 PM, Wolfgang Denk wrote:
Simon Glass wrote:
nit: circular. Just a suggestion if you like: you could also offer guidance for the location of the buffer, something like:
You can place the buffer at the top of memory by adding something like this in your board config file:
#define CONFIG_PRE_CON_BUF_ADDR (CONFIG_SYS_INIT_RAM_ADDR
- \ CONFIG_SYS_INIT_RAM_SIZE - \ CONFIG_PRE_CON_BUF_SZ)
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_PRE_CON_BUF_ADDR - \ GENERATED_GBL_DATA_SIZE)
That would only make sense if these were generic options that are used across all boards and architectures.
Yes ok - its' already decided not to put this code in arch/xxx/board.c so let's leave this out then.
fwiw, i'll probably do that in Blackfin's default arch config.h so that boards get a sane default that'll work across all Blackfin cpus -mike

On Wed, Aug 31, 2011 at 1:22 PM, Mike Frysinger vapier@gentoo.org wrote:
On Wednesday, August 31, 2011 16:05:38 Simon Glass wrote:
On Wed, Aug 31, 2011 at 12:18 PM, Wolfgang Denk wrote:
Simon Glass wrote:
nit: circular. Just a suggestion if you like: you could also offer guidance for the location of the buffer, something like:
You can place the buffer at the top of memory by adding something like this in your board config file:
#define CONFIG_PRE_CON_BUF_ADDR (CONFIG_SYS_INIT_RAM_ADDR
- \ CONFIG_SYS_INIT_RAM_SIZE - \ CONFIG_PRE_CON_BUF_SZ)
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_PRE_CON_BUF_ADDR - \ GENERATED_GBL_DATA_SIZE)
That would only make sense if these were generic options that are used across all boards and architectures.
Yes ok - its' already decided not to put this code in arch/xxx/board.c so let's leave this out then.
fwiw, i'll probably do that in Blackfin's default arch config.h so that boards get a sane default that'll work across all Blackfin cpus
SGTM - this sort of address arithmetic in every board header file is a bit ick.
-mike

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.
--- Changes since V4 - Fixed typo in README - Made *pre_console* functions in console.c static - Slight tweak to commit message - Some may choose to set the configuration defines at the arch level
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
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- 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..cf6c01f 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 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. 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..f17875e 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) + +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; }
-- 1.7.5.2.317.g391b14

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.
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- Grrrr - Repost of V5 with an SoB. There has to be a better way of automating patch updates ;)
Changes since V4 - Fixed typo in README - Made *pre_console* functions in console.c static - Slight tweak to commit message - Some may choose to set the configuration defines at the arch level
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..cf6c01f 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 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. 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..f17875e 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) + +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; }
-- 1.7.5.2.317.g391b14

On Thursday, September 01, 2011 06:52:06 Graeme Russ wrote:
Grrrr - Repost of V5 with an SoB. There has to be a better way of automating patch updates ;)
`git commit --amend` ? s-o-b tag should be in the changelog and thus not get lost during the normal run of things ... -mike

Hi Graeme,
On Thu, Sep 1, 2011 at 7:02 AM, Mike Frysinger vapier@gentoo.org wrote:
On Thursday, September 01, 2011 06:52:06 Graeme Russ wrote:
Grrrr - Repost of V5 with an SoB. There has to be a better way of automating patch updates ;)
`git commit --amend` ? s-o-b tag should be in the changelog and thus not get lost during the normal run of things ... -mike
I have a script(TM) which pulls the versions, cover letter, to- and cc- addresses from the commits. It also runs them through checkpatch.pl and does its own checks. It makes adding a new version easier because you just have to update 'Series-version: 2' to 'Series-version: 3' for example. It also collects the change lists from the various commits and puts them in the cover letter and emails them out. It's not really U-Boot specific, but it does take a monkey work out of sending out U-Boot patches.
Perhaps it would help?
Regards, Simon

Hi Simon,
On Fri, Sep 2, 2011 at 4:51 AM, Simon Glass sjg@chromium.org wrote:
Hi Graeme,
On Thu, Sep 1, 2011 at 7:02 AM, Mike Frysinger vapier@gentoo.org wrote:
On Thursday, September 01, 2011 06:52:06 Graeme Russ wrote:
Grrrr - Repost of V5 with an SoB. There has to be a better way of automating patch updates ;)
`git commit --amend` ? s-o-b tag should be in the changelog and thus not get lost during the normal run of things ... -mike
I have a script(TM) which pulls the versions, cover letter, to- and cc- addresses from the commits. It also runs them through checkpatch.pl and does its own checks. It makes adding a new version easier because you just have to update 'Series-version: 2' to 'Series-version: 3' for example. It also collects the change lists from the various commits and puts them in the cover letter and emails them out. It's not really U-Boot specific, but it does take a monkey work out of sending out U-Boot patches.
Perhaps it would help?
Could you send it through please?
It would be neat if we could grab the Message-ID from get-send-email and track so that In-Replt-To: can be automatically set for the next version
Regards,
Graeme

On Thursday, September 01, 2011 19:34:51 Graeme Russ wrote:
It would be neat if we could grab the Message-ID from get-send-email and track so that In-Replt-To: can be automatically set for the next version
ive always just viewed the raw e-mail (in kmail, just hit "v" to view everything) and copied & pasted it into git send-email.
but a script that would connect to gmane's nntp interface, fetch the headers, and then auto d/l the relevant thread and extract the message id would be pretty cool. -mike

Hi Graeme,
On Thu, Sep 1, 2011 at 4:34 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Simon,
On Fri, Sep 2, 2011 at 4:51 AM, Simon Glass sjg@chromium.org wrote:
Hi Graeme,
On Thu, Sep 1, 2011 at 7:02 AM, Mike Frysinger vapier@gentoo.org wrote:
On Thursday, September 01, 2011 06:52:06 Graeme Russ wrote:
Grrrr - Repost of V5 with an SoB. There has to be a better way of automating patch updates ;)
`git commit --amend` ? s-o-b tag should be in the changelog and thus not get lost during the normal run of things ... -mike
I have a script(TM) which pulls the versions, cover letter, to- and cc- addresses from the commits. It also runs them through checkpatch.pl and does its own checks. It makes adding a new version easier because you just have to update 'Series-version: 2' to 'Series-version: 3' for example. It also collects the change lists from the various commits and puts them in the cover letter and emails them out. It's not really U-Boot specific, but it does take a monkey work out of sending out U-Boot patches.
Perhaps it would help?
Could you send it through please?
Yes will put it in the queue behind the sandbox patches. It needs a little clean up. Should I do it as a patch against the tools directory?
It would be neat if we could grab the Message-ID from get-send-email and track so that In-Replt-To: can be automatically set for the next version
Should be possible although I haven't anything like that. I do have a library which filters terminal output as it displays it though, which might suit for watching git send-email.
Regards, Simon
Regards,
Graeme

Hi Graeme,
On Thu, Sep 1, 2011 at 3:52 AM, Graeme Russ graeme.russ@gmail.com wrote:
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.
Signed-off-by: Graeme Russ graeme.russ@gmail.com
I tested this on a Tegra2 Seaboard.
Tested-by: Simon Glass sjg@chromium.org
Regards, Simon
Grrrr - Repost of V5 with an SoB. There has to be a better way of automating patch updates ;)
Changes since V4 - Fixed typo in README - Made *pre_console* functions in console.c static - Slight tweak to commit message - Some may choose to set the configuration defines at the arch level
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..cf6c01f 100644
[snip]

Hi Graeme,
On Wed, Sep 21, 2011 at 4:18 PM, Simon Glass sjg@chromium.org wrote:
Hi Graeme,
On Thu, Sep 1, 2011 at 3:52 AM, Graeme Russ graeme.russ@gmail.com wrote:
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.
Signed-off-by: Graeme Russ graeme.russ@gmail.com
I tested this on a Tegra2 Seaboard.
Tested-by: Simon Glass sjg@chromium.org
Further to this, I pushed it a little further and managed to get early console output from the AVP (an ARM7) before the Cortex-A9s are fired up on a Tegra20/30. That's pretty early!
This is a great patch and very useful for early bring-up I think. I hope it will be merged this window. Any other comments?
Regards, Simon
Regards, Simon
Grrrr - Repost of V5 with an SoB. There has to be a better way of automating patch updates ;)
Changes since V4
- Fixed typo in README
- Made *pre_console* functions in console.c static
- Slight tweak to commit message - Some may choose to set the
configuration defines at the arch level
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..cf6c01f 100644
[snip]

Dear Graeme Russ,
In message 1314874326-10231-1-git-send-email-graeme.russ@gmail.com you wrote:
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.
Signed-off-by: Graeme Russ graeme.russ@gmail.com
Grrrr - Repost of V5 with an SoB. There has to be a better way of automating patch updates ;)
Changes since V4
- Fixed typo in README
- Made *pre_console* functions in console.c static
- Slight tweak to commit message - Some may choose to set the configuration defines at the arch level
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(-)
Applied, thanks.
Best regards,
Wolfgang Denk

On Wed, Aug 31, 2011 at 5:58 AM, Graeme Russ graeme.russ@gmail.com wrote:
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@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 ++
I know I am late to the party here, but all of a sudden I need to implement something similar, albeit slightly different:
- the memory could be allocated by the "cold bootprom" which starts u-boot; - all console output needs to be saved, not just until the moment when the console hardware is initialized.
I could work on top of this patch and send another one once this one has been accepted. May I suggest an improvement though:
is it really necessary to store the index in the global data structure. This requires editing all these .h files adding another unsighty conditionally compiled field. Why not to store the index as the first word in the buffer allocated for this temp storage?
cheers, /vb
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
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Hi Vadim,
On 27/09/11 08:50, Vadim Bendebury wrote:
On Wed, Aug 31, 2011 at 5:58 AM, Graeme Russ graeme.russ@gmail.com wrote:
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@gmail.com
[snip]
I know I am late to the party here, but all of a sudden I need to implement something similar, albeit slightly different:
better late than never :)
- the memory could be allocated by the "cold bootprom" which starts u-boot;
Typically, the pre-console buffer would exist in the CPU cache (or similar non-(S)DRAM location)
- all console output needs to be saved, not just until the moment when
the console hardware is initialized.
That could be a _huge_ amount of info and highly variable. Remember, the available space for a pre-console buffer could be tiny. If this is needed, then maybe look at forking stdio instead (one branch to console, one branch to you console buffer)
I could work on top of this patch and send another one once this one has been accepted. May I suggest an improvement though:
is it really necessary to store the index in the global data structure. This requires editing all these .h files adding another unsighty conditionally compiled field. Why not to store the index as the first word in the buffer allocated for this temp storage?
I like this - but instead:
struct pre_con_buff { int idx; char *buffer[CONFIG_PRE_CON_BUF_SZ]; }
struct pre_con_buff *pre_con_buffer;
pre_con_buffer = (struct pre_con_buff *)CONFIG_PRE_CON_BUF_ADDR;
Regards,
Graeme

On Tue, Sep 27, 2011 at 4:22 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Vadim,
On 27/09/11 08:50, Vadim Bendebury wrote:
On Wed, Aug 31, 2011 at 5:58 AM, Graeme Russ graeme.russ@gmail.com wrote:
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@gmail.com
[snip]
I know I am late to the party here, but all of a sudden I need to implement something similar, albeit slightly different:
better late than never :)
- the memory could be allocated by the "cold bootprom" which starts u-boot;
Typically, the pre-console buffer would exist in the CPU cache (or similar non-(S)DRAM location)
hi Graeme,
Actually, there are many cases when u-boot starts running with memory fully initialized - ARM platforms is one case and coreboot/u-boot combination on x86 is another, but in general, yes, this buffer could be mapped to the internal CPU memory nailed to a fixed address.
- all console output needs to be saved, not just until the moment when
the console hardware is initialized.
That could be a _huge_ amount of info and highly variable. Remember, the available space for a pre-console buffer could be tiny. If this is needed, then maybe look at forking stdio instead (one branch to console, one branch to you console buffer)
Sure, if the room in the preallocated buffer is not enough, only the most recent data fitting in the space would be kept.
I don't quite understand what you mean by "forking stdio". I was thinking about introducing a separate driver for this memory stored console output, but sjg@ explained that while running from ROM u-boot supports only one console interface, so there is no way to have console stream sent to more than one driver before relocation.
I could work on top of this patch and send another one once this one has been accepted. May I suggest an improvement though:
is it really necessary to store the index in the global data structure. This requires editing all these .h files adding another unsighty conditionally compiled field. Why not to store the index as the first word in the buffer allocated for this temp storage?
I like this - but instead:
struct pre_con_buff { int idx; char *buffer[CONFIG_PRE_CON_BUF_SZ]; }
struct pre_con_buff *pre_con_buffer;
pre_con_buffer = (struct pre_con_buff *)CONFIG_PRE_CON_BUF_ADDR;
yes, this is exactly what I meant,
cheers, /vb
Regards,
Graeme

Hi Vadim,
On Wed, Sep 28, 2011 at 12:55 AM, Vadim Bendebury vbendeb@chromium.org wrote:
On Tue, Sep 27, 2011 at 4:22 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Vadim,
On 27/09/11 08:50, Vadim Bendebury wrote:
On Wed, Aug 31, 2011 at 5:58 AM, Graeme Russ graeme.russ@gmail.com wrote:
[snip]
Typically, the pre-console buffer would exist in the CPU cache (or similar non-(S)DRAM location)
hi Graeme,
Actually, there are many cases when u-boot starts running with memory fully initialized - ARM platforms is one case and coreboot/u-boot combination on x86 is another, but in general, yes, this buffer could be mapped to the internal CPU memory nailed to a fixed address.
And we have to satisfy the 'absolute majority', not the 'many' or the 'simply majority'. And I'm not sure it's always true that ARM platforms have fully initialised SDRAM when U-Boot starts
- all console output needs to be saved, not just until the moment when
the console hardware is initialized.
That could be a _huge_ amount of info and highly variable. Remember, the available space for a pre-console buffer could be tiny. If this is needed, then maybe look at forking stdio instead (one branch to console, one branch to you console buffer)
Sure, if the room in the preallocated buffer is not enough, only the most recent data fitting in the space would be kept.
I don't quite understand what you mean by "forking stdio". I was
Search for CONFIG_CONSOLE_MUX - There appears to be support for sending stdout to multiple output devices:
static void console_putc(int file, const char c) { int i; struct stdio_dev *dev;
for (i = 0; i < cd_count[file]; i++) { dev = console_devices[file][i]; if (dev->putc != NULL) dev->putc(c); } }
I don't know have to register additional devices though
thinking about introducing a separate driver for this memory stored console output, but sjg@ explained that while running from ROM u-boot supports only one console interface, so there is no way to have console stream sent to more than one driver before relocation.
Yes, while running from ROM your options are very limited, but if you have a console buffer big enough to get you into RAM you can do lot more
I could work on top of this patch and send another one once this one has been accepted. May I suggest an improvement though:
is it really necessary to store the index in the global data structure. This requires editing all these .h files adding another unsighty conditionally compiled field. Why not to store the index as the first word in the buffer allocated for this temp storage?
I like this - but instead:
struct pre_con_buff { int idx; char *buffer[CONFIG_PRE_CON_BUF_SZ]; }
struct pre_con_buff *pre_con_buffer;
pre_con_buffer = (struct pre_con_buff *)CONFIG_PRE_CON_BUF_ADDR;
yes, this is exactly what I meant,
Thinking more about this, I think I prefer the current patch for two reasons:
1) gd is guaranteed to be cleared - The memory holding the buffer is not so you would need to initialise it somehow - That could mean splitting the init for each arch 2) pre_con_buffer is larger than CONFIG_PRE_CON_BUF_SZ. This will need to be taken into consideration if the buffer is being crammed into a very tightly crafted memory map - Forgetting to take this into account is going to cause lots of pain. Now you could do:
struct pre_con_buff { u16 idx; char *buffer[CONFIG_PRE_CON_BUF_SZ - 2]; }
but the buffer size should really be a power two (so the compiler optimises the divides into shifts) - So now we have to define CONFIG_PRE_CON_BUF_SZ as say 258. It's starting to get messy
Regards,
Graeme

On Thu, Sep 29, 2011 at 4:15 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Vadim,
On Wed, Sep 28, 2011 at 12:55 AM, Vadim Bendebury vbendeb@chromium.org wrote:
On Tue, Sep 27, 2011 at 4:22 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Vadim,
On 27/09/11 08:50, Vadim Bendebury wrote:
On Wed, Aug 31, 2011 at 5:58 AM, Graeme Russ graeme.russ@gmail.com wrote:
[snip]
Typically, the pre-console buffer would exist in the CPU cache (or similar non-(S)DRAM location)
hi Graeme,
Actually, there are many cases when u-boot starts running with memory fully initialized - ARM platforms is one case and coreboot/u-boot combination on x86 is another, but in general, yes, this buffer could be mapped to the internal CPU memory nailed to a fixed address.
And we have to satisfy the 'absolute majority', not the 'many' or the 'simply majority'. And I'm not sure it's always true that ARM platforms have fully initialised SDRAM when U-Boot starts
- all console output needs to be saved, not just until the moment when
the console hardware is initialized.
That could be a _huge_ amount of info and highly variable. Remember, the available space for a pre-console buffer could be tiny. If this is needed, then maybe look at forking stdio instead (one branch to console, one branch to you console buffer)
Sure, if the room in the preallocated buffer is not enough, only the most recent data fitting in the space would be kept.
I don't quite understand what you mean by "forking stdio". I was
Search for CONFIG_CONSOLE_MUX - There appears to be support for sending stdout to multiple output devices:
static void console_putc(int file, const char c) { int i; struct stdio_dev *dev;
for (i = 0; i < cd_count[file]; i++) { dev = console_devices[file][i]; if (dev->putc != NULL) dev->putc(c); } }
I don't know have to register additional devices though
hi Graeme,
sure, I understand how the console mux works, i was not sure you were referring to it.
thinking about introducing a separate driver for this memory stored console output, but sjg@ explained that while running from ROM u-boot supports only one console interface, so there is no way to have console stream sent to more than one driver before relocation.
Yes, while running from ROM your options are very limited, but if you have a console buffer big enough to get you into RAM you can do lot more
I could work on top of this patch and send another one once this one has been accepted. May I suggest an improvement though:
is it really necessary to store the index in the global data structure. This requires editing all these .h files adding another unsighty conditionally compiled field. Why not to store the index as the first word in the buffer allocated for this temp storage?
I like this - but instead:
struct pre_con_buff { int idx; char *buffer[CONFIG_PRE_CON_BUF_SZ]; }
struct pre_con_buff *pre_con_buffer;
pre_con_buffer = (struct pre_con_buff *)CONFIG_PRE_CON_BUF_ADDR;
yes, this is exactly what I meant,
Thinking more about this, I think I prefer the current patch for two reasons:
1) gd is guaranteed to be cleared - The memory holding the buffer is not so you would need to initialise it somehow - That could mean splitting the init for each arch
doesn't each console type have an init routine? this would be a place to initialize the header.
2) pre_con_buffer is larger than CONFIG_PRE_CON_BUF_SZ. This will need to be taken into consideration if the buffer is being crammed into a very tightly crafted memory map - Forgetting to take this into account is going to cause lots of pain. Now you could do:
struct pre_con_buff { u16 idx; char *buffer[CONFIG_PRE_CON_BUF_SZ - 2]; }
I actually have just implemented this for coreboot. It has its own idiosyncrasies of course, the console buffer needs to be kept in three different places and the contents copied three times on the way up.
I used this structure for the log buffer:
struct pre_con_buff { u16 size; u16 idx; char buffer[0] };
Then, the initialization code would just get the memory area address and size, overlay this structure on top of it and set the size field to
<area size> - sizeof(struct pre_con_buff)
yes, this results in a non power of two buffer size, but IMO the convenience of keeping everything in one place and (and not changing multiple .h files) is worth the lost performance of not being able to utilize power of two arithmetic optimization (which I think is negligible in any case).
cheers, /vb
but the buffer size should really be a power two (so the compiler optimises the divides into shifts) - So now we have to define CONFIG_PRE_CON_BUF_SZ as say 258. It's starting to get messy
Regards,
Graeme

Hi Vladim
On Fri, Sep 30, 2011 at 9:39 AM, Vadim Bendebury vbendeb@chromium.org wrote:
On Thu, Sep 29, 2011 at 4:15 PM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Vadim,
On Wed, Sep 28, 2011 at 12:55 AM, Vadim Bendebury vbendeb@chromium.org wrote:
On Tue, Sep 27, 2011 at 4:22 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi Vadim,
On 27/09/11 08:50, Vadim Bendebury wrote:
On Wed, Aug 31, 2011 at 5:58 AM, Graeme Russ graeme.russ@gmail.com wrote:
[snip]
- gd is guaranteed to be cleared - The memory holding the buffer is not
so you would need to initialise it somehow - That could mean splitting the init for each arch
doesn't each console type have an init routine? this would be a place to initialize the header.
The point is that with pre-console buffer, we have a storage location for console output even before any console init routine is run - console is available as soon as gd is cleared (which is _very_ early indeed)
- pre_con_buffer is larger than CONFIG_PRE_CON_BUF_SZ. This will need to
be taken into consideration if the buffer is being crammed into a very tightly crafted memory map - Forgetting to take this into account is going to cause lots of pain. Now you could do:
struct pre_con_buff { u16 idx; char *buffer[CONFIG_PRE_CON_BUF_SZ - 2]; }
I actually have just implemented this for coreboot. It has its own idiosyncrasies of course, the console buffer needs to be kept in three different places and the contents copied three times on the way up.
Ouch!
I used this structure for the log buffer:
struct pre_con_buff { u16 size; u16 idx; char buffer[0] };
Then, the initialization code would just get the memory area address and size, overlay this structure on top of it and set the size field to
<area size> - sizeof(struct pre_con_buff)
For U-Boot, that sounds like a lot of stuffing around to save two bytes in gd
yes, this results in a non power of two buffer size, but IMO the convenience of keeping everything in one place and (and not changing multiple .h files) is worth the lost performance of not being able to utilize power of two arithmetic optimization (which I think is negligible in any case).
In an embedded bootloader, every clock counts :) - You desktop junkies are too used to long boot times ;)
but the buffer size should really be a power two (so the compiler optimises the divides into shifts) - So now we have to define CONFIG_PRE_CON_BUF_SZ as say 258. It's starting to get messy
And messier (at least in the context of U-Boot - YMMV)
Regards,
Graeme
participants (5)
-
Graeme Russ
-
Mike Frysinger
-
Simon Glass
-
Vadim Bendebury
-
Wolfgang Denk