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

Vadim Bendebury vbendeb at chromium.org
Tue Sep 27 00:50:52 CEST 2011


On Wed, Aug 31, 2011 at 5:58 AM, Graeme Russ <graeme.russ at 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 at gmail.com>
> ---
> Changes since V3
>  - Fixed  blank subject caused by gap between the Cc: list and Date:
>
> Changes since V2
>  - Cast buffer size to unsigned long to help compilers produce tighter
>   code
>  - Use inline stub functions to reduce #ifdef clutter
>  - Add documentation to README
>
> Changes Since V1
>  - Implemented circular buffer
>  - Trivial code styl corrections
>
>  README                                    |   14 +++++++++
>  arch/arm/include/asm/global_data.h        |    3 ++
>  arch/avr32/include/asm/global_data.h      |    3 ++
>  arch/blackfin/include/asm/global_data.h   |    3 ++
>  arch/m68k/include/asm/global_data.h       |    3 ++
>  arch/microblaze/include/asm/global_data.h |    3 ++
>  arch/mips/include/asm/global_data.h       |    3 ++
>  arch/nios2/include/asm/global_data.h      |    3 ++
>  arch/powerpc/include/asm/global_data.h    |    3 ++
>  arch/sh/include/asm/global_data.h         |    3 ++
>  arch/sparc/include/asm/global_data.h      |    3 ++
>  arch/x86/include/asm/global_data.h        |    3 ++

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 at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>


More information about the U-Boot mailing list